![为什么波形符前缀会在赋值之前展开,而大括号则不会](https://linux22.com/image/143102/%E4%B8%BA%E4%BB%80%E4%B9%88%E6%B3%A2%E5%BD%A2%E7%AC%A6%E5%89%8D%E7%BC%80%E4%BC%9A%E5%9C%A8%E8%B5%8B%E5%80%BC%E4%B9%8B%E5%89%8D%E5%B1%95%E5%BC%80%EF%BC%8C%E8%80%8C%E5%A4%A7%E6%8B%AC%E5%8F%B7%E5%88%99%E4%B8%8D%E4%BC%9A.png)
tl;目录
在 bash 中,大括号扩展发生在波形符扩展之前。然而,波形符前缀似乎在变量赋值之前扩展,而大括号扩展则不然。为什么?
详细信息和示例
大括号扩展在任何其他扩展之前执行
据我了解,波形符扩展发生在变量赋值之前,如以下示例所示:
# UNQUOTED TILDE PREFIX, TILDE EXPANSION EXPECTED
tilde=~
echo "$tilde"
# /Users/DeNovo
[[ $tilde == "$HOME" ]] && echo "literal match"
# literal match
# QUOTED TILDE PREFIX, TILDE EXPANSION DOES NOT OCCUR
lit_tilde='~'
echo "$lit_tilde"
# ~
# UNQUOTED TILDE PREFIX PRODUCED AND EVALUATED, TILDE EXPANSION OCCURS
# AS EXPECTED
eval echo "$lit_tilde"
# /Users/DeNovo
[[ $lit_tilde == "~" ]] && echo "literal match"
# literal match
这些示例似乎表明,右操作数left=right
在作为值绑定到左操作数之前会经历波形符扩展。
但是,大括号扩展不会在变量赋值之前发生,其行为与将文字波形符绑定到变量类似(与扩展的特殊字符/前缀相比)
# UNQUOTED BRACE, BUT NO EXPANSION. BRACE LITERAL IS PRESERVED
brace={a..c}
echo "$brace"
# {a..c}
[[ $brace = "a b c" ]] || echo "doesn't match"
# doesn't match
[[ $brace = "{a..c}" ]] && echo "literal match"
# literal match
# SIMILAR TO THE LITERAL TILDE, EVALUATING THE VARIABLE VALUE
# RESULTS IN BRACE EXPANSION
eval echo "$brace"
# a b c
将这两种扩展合并到一个示例中,您可以看到波形符扩展发生,而大括号扩展不发生:
combined=~/dir_{a..c}
echo "$combined"
# /Users/DeNovo/dir_{a..c}
大括号可防止内部波形符在赋值期间扩展
internal_tilde={~,~+}/new_dir
echo "$internal_tilde"
# {~,~+}/new_dir
# vs the same output, not in a variable
echo {~,~+}/new_dir
/Users/DeNovo/new_dir /Your/Working/Directory/new_dir
只是为了澄清,我不是问如何让变量包含大括号扩展的结果,而是问为什么尽管发生在波形符扩展之前,但大括号扩展不会在变量赋值之前发生。有多种方法可以获得所需的行为。这是一个:
# PROCESS SUBSTITUTION GIVES THE DESIRED BEHAVIOR
brace_exp="$(echo {a..c})"
echo "$brace_exp"
a b c
[[ $brace_exp = "a b c" ]] && echo "literal match"
# literal match
再说一次,为什么波浪号扩展发生在变量赋值之前,但大括号扩展(应该发生在波浪号扩展之前)不会发生在变量赋值之前。想必作业在某种程度上是我不知道的特殊之处。
答案1
答案2
@StephenKitt 的答案指向相关文档(+1),表明该行为是预期的(为什么波浪号前缀在赋值之前扩展,而大括号则不扩展?因为这就是它们的定义方式)。
回复:大括号扩展特殊的一个可能原因,让我们看看是什么不发生在变量赋值时:
- 大括号扩展
- 单词拆分(解析器拆分行,但不拆分该单词内的扩展结果)
- 文件名扩展
这些正是可以改变扩展字数的操作:
外壳膨胀:
只有大括号扩展、分词和文件名扩展可以更改扩展的字数
在示例情况中,变量是字符串而不是数组,并且应仅包含一个单词。
支撑扩张做分配数组时发生,如brace=({a..c})
.使用更复杂的示例:
internal_tilde=({~,~+}/new_dir)
echo "${internal_tilde[@]}"
# /Users/DeNovo/new_dir /Your/Working/Directory/new_dir
因此,我认为这种设计是有意义的(而不是历史上的奇怪现象)。波形符扩展不会改变单词数。大括号扩展确实如此。如果您希望变量包含多个单词,请使用专门为此设计的数据结构。