解释:bash,Note that if no expansion occurs, no splitting is performed.
这句话是 Bash Shell 对“单词拆分”(word splitting)行为的重要说明。
我会一步步解释它。
1. 上下文
这句话通常出现在 Bash 对 参数扩展(parameter expansion)、命令替换(command substitution) 或 算术扩展(arithmetic expansion) 的介绍中。
Bash 处理一个命令时,在解析阶段会进行多个步骤,其中包括:
- 识别 token
- 执行各种扩展(比如
$VAR、$(command)、$((1+2))等) - 单词拆分(Word Splitting)
- 文件名生成(globbing)
2. 什么是“单词拆分”?
单词拆分 是指:
如果一个扩展的结果是一个未经引号包裹的字符串,Bash 会按照 IFS(内部字段分隔符)变量的值(默认是空格、制表符、换行符)把这个字符串拆分成多个单词(字段),每个单词成为命令行的一个独立参数。
例子:
VAR="file1 file2 file3"
touch $VAR
这里 $VAR 扩展成 "file1 file2 file3",因为没加双引号,所以 Bash 会将其拆分成三个参数:file1、file2、file3,然后传给 touch。
3. 如果加了双引号会怎样?
VAR="file1 file2 file3"
touch "$VAR"
此时 "$VAR" 是一个整体,不进行单词拆分,所以 touch 只收到一个参数 "file1 file2 file3",它会尝试创建一个名字中间有空格的单个文件。
4. “No expansion occurs, no splitting is performed” 的含义
现在看这句话的重点:
单词拆分只作用于“发生了扩展”的地方的结果。
例子:
VAR="file1 file2 file3"
touch $VAR
$VAR发生了扩展(扩展成file1 file2 file3)。- 因为它没加引号,所以对扩展的结果进行单词拆分。
但如果是:
touch file1 file2 file3
- 这里的
file1、file2、file3是直接写的字面量,没有发生任何扩展(没有$、$(...)等)。 - 那么 Bash 不会对它们进行“单词拆分”,因为它们已经是分开的单词。
- 更准确说:单词拆分这一步根本不考虑它们,因为它们原本就是被空格分开的单词(在解析的早期就已经是三个 token)。
再举一个无扩展的例子:
cmd="touch file1 file2"
$cmd
这里 $cmd 发生了扩展(扩展成 touch file1 file2),然后 Bash 对结果进行单词拆分,得到 touch、file1、file2 三个单词,然后再执行 touch file1 file2。
5. 为什么要强调这句话?
因为它澄清了一个常见误解:有人可能以为“Bash 总是按空格拆分命令行”。
实际上:
- Bash 在解析命令行时,一开始就会根据元字符(空格、引号、管道等)划分单词(这个过程叫 tokenization)。
- 之后进行的单词拆分(Word Splitting) 是“扩展阶段”的一个子步骤,只对“未加引号的扩展结果”进行。
- 如果命令行中某个部分根本没有发生扩展,那它已经是以单词形式存在了,就不存在“拆分”这一步。
这样能保证:
echo a b c
始终是三个参数,而不会因为某些奇怪的 IFS 设置把 a b c 再拆一次(因为它们不是扩展的结果)。
6. 总结成简单说法
单词拆分只作用于“未加引号的扩展结果”。如果某个地方没有发生扩展,那它已经是最终单词,不需要再拆分。
这句话是为了让你理解 Bash 的执行阶段,避免对普通字面量字符串产生不必要的担心。
