Bash不执行分词与通配符扩展的场景有哪些?是否有明确列表?
嘿,这问题问得好!确实有明确的规则可以参考,咱们先把Bash不会执行分词和通配符扩展的核心场景梳理清楚,再给你说规则的来源:
一、赋值语句的左侧或右侧(索引数组赋值除外)
不管是简单变量赋值,还是关联数组的索引/值赋值,这里都不会触发分词和通配符扩展。但要注意,要是给索引数组直接赋值(比如arr=(1 2 3)),或者用命令替换给数组赋值时,还是会执行分词的。
示例代码:
var=$value # 简单变量,不会执行分词和通配符扩展 declare -A hash key="key with a space" hash[$key]=$value # 关联数组的索引,不会触发扩展 arr=$(echo "1 2 3") # 此处会执行分词(命令替换的输出会经过单词拆分)
二、[[ ]]条件判断内部
在[[ ... ]]这个条件结构里,变量引用和命令替换都不会触发分词和通配符扩展,这也是为什么用[[ ]]比[ ]更安全的原因之一——不用额外给变量加引号也能避免意外拆分。
示例代码:
var="one two" if [[ $var = *" "* ]]; then # 检查变量var中是否包含空格,这里$var不会被分词,*也不会被通配扩展 echo "变量里有空格!" fi if [[ $(echo "one two") = $var ]]; then # 命令替换的输出直接作为整体比较,不会被分词 echo "内容匹配!" fi
三、(( ))算术运算内部
在算术扩展的(( ... ))结构里,所有的变量引用和命令替换都不会触发分词或通配符扩展,这里只做算术相关的解析计算。
示例代码:
((sum = $(echo "99 + 1"))) # 命令替换的输出直接作为算术表达式解析,不会分词,sum最终为100
四、Here-string中
Here-string(<<<)的内容会被当作单个完整字符串传递,不会触发分词或通配符扩展。
示例代码:
cat <<< * # 输出就是字符'*',不会匹配当前目录下的文件
五、case语句的模式匹配中
当case语句里用$var作为匹配对象时,$var不会被分词,会作为一个整体去匹配设定的模式。
示例代码:
var="hello world" case $var in "hello world") echo "matches!";; *) echo "no match";; esac # 这里$var不会被拆分成"hello"和"world"两个词,而是作为整体匹配
关于明确规则列表的说明
Bash的官方手册(man bash)里详细定义了扩展的执行顺序和上下文,分词(单词拆分,Word Splitting)和通配符扩展(路径名扩展,Pathname Expansion)是在命令行参数展开的特定阶段执行的——只有当文本出现在“命令参数”或“数组赋值的元素列表”这类需要拆分多个参数的场景时,才会触发这两个扩展。上面提到的这些场景,都属于手册中明确说明的“抑制单词拆分和路径名扩展”的情况。
简单来说,只要不是在“需要拆分出多个独立参数”的场景下,Bash就会把内容当作单个整体处理,不会执行分词和通配符扩展。
内容的提问来源于stack exchange,提问作者codeforester

