我偶然发现了以下bash行为,这对我来说有点出乎意料。
# The following works
$ declare bar=Hello # Line 1
$ declare -p bar # Line 2
declare -- bar="Hello"
$ foo=bar # Line 3
$ declare ${foo}=Bye # Line 4
$ declare -p bar # Line 5
declare -- bar="Bye"
# The following fails, though
$ declare -a array=( A B C ) # Line 6
$ declare -p array # Line 7
declare -a array=([0]="A" [1]="B" [2]="C")
$ foo=array # Line 8
$ declare -a ${foo}=([0]="A" [1]="XXX" [2]="C") # Line 9
bash: syntax error near unexpected token `('`
# Quoting the assignment fixes the problem
$ declare -a "${foo}=(A YYY C)" # Line 10
$ declare -p array # Line 11
declare -a array=([0]="A" [1]="YYY" [2]="C")
Run Code Online (Sandbox Code Playgroud)
由于壳膨胀
在将其拆分为标记(然后是去除引号)之后在命令行上执行,但在执行最终命令之前,我不希望第 9 行失败。
它背后的基本原理是什么,这使得bash不接受第 9 行?或者,换种说法,我在第 9 行的处理方式中遗漏了什么bash使其失败但使第 10 行成功?
在任何情况下,引用并不总是直接起作用,如果数组元素是带有空格的字符串,则需要额外注意。
tl;博士; 我认为这只是一个语法怪癖,你不应该假设它背后有一些宏伟的设计。
Bash 正在使用 bison/yacc 生成的解析器,但就像许多其他语言(C、perl 等)一样,它不是一个“干净”的解析器,但它也保持一些状态与parser_state变量中的语法分开/平行。
保存在该状态变量中的标志是PST_ASSIGNOK。当一些被解析为WORD标记的内置函数ASSIGNMENT_BUILTIN在其标志中时,这将被设置。
这种“分配建宏”是local,typeset,declare,alias,export和readonly。
在此类内置函数的右侧赋值之后使用时,PST_ASSIGNOK将指示解析器将括号视为WORD标记的一部分。但它不会更改确定当前标记是否实际上是赋值的规则:由于${foo}=(...)不是可接受的赋值,因此不会将其解析为单个单词,并且括号将触发语法错误,就像 in 一样echo foo(bar)。
解析命令行后,它将被扩展,作为扩展的一部分,任何复合赋值(WORD标记为W_COMPASSIGN) likevar=(1 2)都将执行并替换为var,然后将其作为参数传递给内置函数 like declare。但是,如果declare在所有扩展之后,得到形式为 的参数var=(...),它将再次解析并扩展它自己。
所以,varname=foo; declare "$var=(1 2 3)"可能类似于declare foo='(1 2 3)'. 或 to declare foo=(1 2 3),取决于变量是否已定义:
$ declare 'foo=(1 2 3)'; typeset -p foo
declare -- foo="(1 2 3)"
$ declare foo=(1); typeset -p foo
declare -a foo=([0]="1")
$ declare 'foo=(1 2 3)'; typeset -p foo
declare -a foo=([0]="1" [1]="2" [2]="3")
Run Code Online (Sandbox Code Playgroud)
我认为依赖这种极端情况不是一个好主意:
$ declare 'bar=(1 ( )'; typeset -p bar
declare -- bar="(1 ( )"
$ declare bar=(1); typeset -p bar
declare -a bar=([0]="1")
$ declare 'bar=(1 ( )'; typeset -p bar
bash: syntax error near unexpected token `('
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
350 次 |
| 最近记录: |