Here-string 提供文本并追加换行
Bash 的 here-string 会把一个词展开后的值送给命令的标准输入,并在末尾追加一个换行符。当变量里已经有少量文本,而目标程序从标准输入读取时,这种写法很方便。它省掉了额外的打印命令,但并不保证输入与变量逐字节相同,也不承诺内部一定使用内存、管道或文件。判断是否适用,应看接收方需要什么输入,而不是只比较命令行长度。 接收命令读取之前先完成展开 三个小于号之后的词可以包含变量展开、算术展开和命令替换,因此不一定是字面常量。单引号保留源码中的字面文本,双引号则允许通常的变量和命令展开。通过变量展开得到的字符串,即使包含美元符号和括号,也不会仅因出现在 here-string 中就被再次作为 shell 命令执行。源码中明确写出的替换语法与变量保存的数据必须区分。 当前 Bash 不会对 here-string 的词执行分词或文件名展开,而是把结果作为一个字符串交付。这里引用变量仍能清楚表达意图,但不能把这种重定向上下文和普通命令参数位置混为一谈。后者使用未引用变量时仍可能按空白拆分,或把星号变成文件名。因此,某个值通过 here-string 正常到达,并不能证明在别处省略引号也安全。 末尾追加换行是无条件发生的。原值没有换行时会多一个,原值已经有尾部换行时还会再多一个。空变量也因此产生包含一个换行字节的输入,而不是立即结束的零字节输入。对于按行处理的工具,这常常符合需求;对于严格长度、签名字节或特定结束字符的协议,则可能直接改变意义,不能把它当作原始字节透传方式。 坏掉的样子 Shell 形成输入后,read 还会按自己的规则解释。默认分词可能移除首尾 IFS 空白,反斜杠也可能作为转义符处理。读取需要保留空格和反斜杠的一行时,应使用 IFS= read -r name。它保护的是这一行的内容;单次 read 仍然在第一个换行处结束,并不会自动把任意多行字符串全部装进变量。输入构造规则与消费者解析规则是两个阶段。 带重定向的内建命令或循环可以在当前 shell 中运行,因此其中的赋值能够在后续代码中继续使用。相比把循环放进管道,这有助于避免 Bash 通常为管道阶段创建子 shell 导致的状态丢失。重定向本身不会包上一层子 shell,但如果表达式的其他地方明确使用子 shell 或命令替换,它们仍然具有通常的作用域与副作用,不能因为用了 here-string 就忽略。 ...