
在我的 GNU bash 版本 4.2.8 中,IFS 默认有空格、制表符和换行符的默认值:
usr@T42 ~ $ echo -n "$IFS" | hexdump -C
00000000 20 09 0a | ..|
00000003
usr@T42 ~ $
这种默认的 IFS 是否有原因?另外,除了 bash 内置的之外,还有哪些实用程序使用 IFS read
?
答案1
每次 shell 执行名为的任务时都会使用 IFS 变量分词。最常见的情况是在命令中进行参数扩展(例如$var
)或命令替换(例如或已弃用的反引号)之后。$(some-command)
在这里,如果扩展包含任何IFS
字符,那么在处理命令之前它会分成不同的“单词”。实际上,这意味着这些字符将替换的文本拆分为不同的参数(如果首先指定了变量,则包括命令的名称)。
因此,默认值为空格、制表符和换行符的原因IFS
是,这些是通常期望分割单词的空白字符。
防止分词发生的一种方法是在扩展名 ( "$var"
) 周围使用双引号 - 事实上您已经在问题中这样做了。如果您不这样做,则不会有任何输出,echo
因为它没有参数,只有字符分割参数。
另请注意,分词的两个地方不发生在参数扩展与变量赋值之后(例如,var=$othervar
并且var=$(somecommand)
可以),并且在[[ ]]
构造内([[ $var = $othervar ]]
可以,但[ $var = $othervar ]
应该被引用)。
最后,正如一位智者曾经向我指出的那样,一个常见的误解是,防止分词是最重要的仅有的引用变量的原因。事实并非如此,引用也阻止了路径名扩展或者全球扩张因为它更广为人知。如果变量包含像这样的全局字符,*
那么当在命令中使用不带引号的变量时,这些字符可能会扩展为文件名。例如,考虑:
var=*
echo $var
这将显示当前目录中的文件的名称。
作为斯蒂芬在下面指出,扩展时其中的字符顺序IFS
很重要"$*"
。从bash
手册页:
"$*" is equivalent to "$1c$2c...", where c is the first character of the value of
the IFS variable. If IFS is unset, the parameters are separated by spaces. If
IFS is null, the parameters are joined without intervening separators.
有关分词的更多示例,请参阅此答案 -https://unix.stackexchange.com/a/118444/48083