【发布时间】:2017-01-23 18:40:31
【问题描述】:
我试图弄清楚 IFS 如何影响 bash 中的分词。该行为与上下文相关,其方式似乎与分词的直觉不符。
总体思路似乎很简单。引用 bash 手册页:
shell 将 IFS 的每个字符视为分隔符,并将其他扩展的结果拆分为这些字符上的单词。 ...请注意,如果没有发生扩展,则不执行拆分。
这可以很容易地验证,例如通过将 IFS 变量设置为 ',' 并使用逗号分隔的参数列表调用 shell 函数。
echo_n () {
echo Num args: $#, Args: "$@"
}
( IFS=','
args=foo,bar,baz
echo_n $args
)
正如预期的那样,这会导致 echo_n 出现三个不同的参数
Num args: 3, Args: foo bar baz
使用逗号分隔的列表直接调用 echo_n 失败,因为没有触发扩展。
IFS=, echo_n foo,bar,baz
结果
Num args: 1, Args: foo,bar,baz
到目前为止,事情似乎相当扭曲,但我可以绕着它们转。当我们开始在图片中添加 for 循环时,事情变得更加复杂。
(IFS=,; for i in foo,bar,baz ; do echo_n $i; done)
结果
Num args: 3, Args: foo bar baz
这违背了 for 循环的目的。
现在,我可以通过几个 bash 技巧中的任何一个来强制 IFS 分词,这些技巧可以强制触发某种形式的扩展。例如:
(IFS=,; for i in ${NO_VAR:-foo,bar,baz} ; do echo_n $i; done)
结果
Num args: 1, Args: foo
Num args: 1, Args: bar
Num args: 1, Args: baz
(诀窍在于使用默认值评估未定义的变量 NO_VAR。)
另一个类似的技巧,依赖于命令替换:
(IFS=,; for i in $(echo foo,bar,baz) ; do echo_n $i; done)
那么问题来了:什么是推荐的惯用方法来控制执行 IFS 分词的上下文?
【问题讨论】:
标签: bash