我注意到了这种令人惊讶的行为,并且不太了解发生了什么:
$ bash -c 'echo [-1]'
1
$ zsh -c 'echo [-1]'
1
命令解析器似乎试图评估一个表达式:
$ echo [1,2,3]
1
$ echo [123-33]
1
因为如果表达式被引用,或者表明一个括号只是一个括号,那么奇怪的评估就被省略了。
$ echo \[123-33]
[123-33]
$ echo [123-33\]
[123-33]
$ echo '[123-33]'
[123-33]
在寻找线索时,我发现了这句话:
注意事项
索引 Bash 关联数组时,始终使用引号。否则静态解析器将不得不假定索引是一个算术表达式。
$ echo '${array[spaced string]}' | shfmt 1:16: not a valid arithmetic operator: string $ echo '${array[dash-string]}' | shfmt ${array[dash - string]}
不知道该怎么做,因为在上下文中没有数组可言echo [1-1]
这当然可能是我自己环境中的某些东西引起的,但是当我检查时,它似乎不是:
$ env -i HOME=$(mktemp -d) bash --noprofile --norc
bash-5.1$ echo [1-1]
1
$ env -i HOME=$(mktemp -d) /bin/bash-4.4 --noprofile --norc
bash-4.4-4.4$ echo [1-1]
1
但是话又说回来,在 ubuntu 盒子上我得到了不同的结果:
$ bash --version | sed 1q; echo [1-1]
GNU bash, version 5.0.17(1)-release (x86_64-pc-linux-gnu)
[1-1]
禁用所有选项不会改变此行为。
for i in `shopt | awk '/on$/ { print $1}'`; do shopt -u $i;done
你知道是什么导致这个括号表达式被求值吗?为什么结果是 1?
1
只有在当前目录中有一个名为的文件时才会发生这种情况。为什么?shell 会通
[-1]
配匹配名为-
or的文件1
。因此,如果存在具有这样一个字符名称的文件,则 glob 匹配并且您将获得文件名。如果不存在这样的文件,则 glob 保持不变。PS:它也适用于
-
: