在这些情况下,Bash 不会在通配符中执行分词:
- 赋值的 LHS 或 RHS,索引数组除外
var=$value # simple variable declare -A hash key="key with a space" hash[$key]=$value # index of an associative array arr=$(echo "1 2 3") # word splitting does happen here
- 里面
[[ ]]
var="one two" if [[ $var = *" "* ]]; then ... # check if var has a space in it if [[ $(echo "one two") = $var ]]; then # use the output of command substitution to compare with var
- 里面
(( ))
((sum = $(echo "99 + 1"))) # assigns 100 to sum
- 在此字符串中
cat <<< * # gives '*' as the output
是否有 Bash 执行或不执行分词和通配符的情况的明确列表?
答案1
这通常是它不能或没有意义的情况,所以非列表上下文。然而,在非列表上下文中,它会执行此操作,但当它导致多个项目或用空格连接这些项目时会发出抱怨。
此外,区分通配符模式匹配和文件名生成或通配符(生成与模式匹配的文件名列表)也很重要。
例如,在 中[[ foo = * ]]
,没有通配符,因为它*
没有扩展到当前目录中的非隐藏文件列表,但*
仍然被解释为模式(这里它返回 true 与模式foo
匹配*
)。
此处的拆分是指在未加引号的参数扩展 ( $param
)、命令替换 ($(...)
和`...`
) 以及算术扩展 ($((...))
和$[...]
) 上完成的隐式拆分,使用$IFS
中的特殊参数列出上下文。
*
下面我们就以这个例子为例。作为模式,它匹配任何字符序列。作为一个 glob,它扩展到当前目录中的所有非隐藏文件(受dotglob
, GLOBIGNORE
...)的影响。
以下适用于bash
,其他 shell 存在变化。
不发生分割和通配符的情况:
引用时(用
'*'
,"*"
,\*
,$'*'
,$"*"
)。在此处的文档中(无论分隔符是否被引用):
cat << EOF * EOF cat << 'EOF' * EOF
算术表达式内部:
echo $((2 * 2))
(*
不是通配符,而是$((...))
经过 split+glob,稍后尝试IFS=4
)array[2 * 2]=4
//${array[2 * 2]}
。exec {array[2*2]}>&1
请注意,unset -v 'a[1]'
([1]
是通配符)中需要引号。((2 * 2))
echo $[2 * 2]
标量变量赋值:
var=*
array[x]=*
hash[key]=*
array=([1]=*)
(尽管旧版本过去常常在那里进行通配,并且例如在当前目录中bash
调用一个文件时会执行不同的操作)。1=foo
var+=*
在关联数组键中:
typeset -A hash; hash[**]=value; v=${hash[**]}
。*
虽然@
很特别。
//在赋值之后
export
//仅在某些情况下:赋值关键字和变量名不能被引用,即使是部分引用,也不能是任何扩展的结果。分配和重定向可能会发生在之前,但不能使用:local
typeset
declare
readonly
=
command
- 好的(没有 split+glob):
export a=*
x=1 < /dev/null export foo a=*
- 不正常(执行 split+glob):
""export a=*
(POSIX 模式除外)command export a=*
export "a"=*
export a\=*
"$(echo export)" a=*
有关更多信息,请访问局部变量赋值需要引号吗?
- 好的(没有 split+glob):
case * in (...); esac
case x in (*); esac
(没有 split+glob,但它*
被视为一种模式,也适用于在未加引号的扩展中找到的通配符,如var=*; case x in ($var)
)。里面
[[...]]
。但请注意,如果=
,==
,运算符的右侧存在未加引号的通配符,则会完成模式匹配!=
。从 4.4 版本开始这里的字符串。在早期版本中,进行了拆分(尽管不是通配符),并且生成的单词与空格连接。
当 shell 处于 POSIX 模式且非交互时,在重定向的目标中:
bash -o posix -c 'echo test > *'
.否则,将执行 split+glob,bash
如果扩展为少于或多于 1 个元素的列表,则会报告错误。