引入
在 bash、zsh、csh 等等各种 shell 实现中,都有一个特殊的内置变量 IFS(Internal Field Separator),意为内部字段分隔符。IFS变量值是一个字符序列,shell会将IFS字符序列中的各个字符视为 词分割(word splitting) 过程中分隔不同token的边界。
正文
1. 什么是词分割以及什么情况下会进行词分割
首先,先看一个 “魔法” 来引出我们的话题:
好奇怪,明明我们nums变量中数字间隔是凌乱的,为啥 echo
命令输出之后又变得整整齐齐?莫非是 echo
可以自动排版?echo
当然没有智能这种地步,这里的原因是 shell 在 nums 变量展开时 “偷偷地” 进行了词分割,把原本完整的字符串,分成了 ‘1’, ‘2’, ‘3’, ‘4’, ‘5’ 五个子字符串(token)。echo同时打印五个参数,并会默认在不同参数间添加单个空格输出,这样就有了最终整齐的输出效果。
那我们怎么把 nums 原来的模样打印出来,防止被偷偷整容呢?通过显式地添加引号即可禁止词分割。
为了让显示的效果更明显,我在第二条命令中通过转义的方式在两侧添加了两个字面的双引号,如果觉得有些眼花缭乱,那么只看第一条就好了。
在 shell 中,命令的运行结果常以字符串类型返回,此时 shell 自动的将这个结果字符串根据规定好的分隔符切分成多个不同的子字符串(token),这一过程就是词分割。词分割会在参数展开、命令替换、算术展开以及读取输入的过程中发生。这里所谓 “规定好的分隔符” 即IFS变量中所包含的字符,IFS值默认为一个空格、一个制表符和一个换行符,因此默认情况下以 [ \t\n]+
作为词分割的分隔符。同时,词分割时会忽略掉字符串开头和结尾的分隔符。
2. 自定义分隔符
除了默认的以空白符作为分隔符之外,我们也可以通过给 IFS 重新赋值修改词分割的分隔符。为更好地展示效果,定义如下函数:
function report_n_args {
echo "$# args:"
for arg in "$@"
do
echo -n "'$arg' "
done
echo
}
2.1 参数展开(zsh默认在参数展开时不做词分割)
需要注意的是,当空白符作为分隔符时,连续的空白符视作一个分隔符;当非空白字符作为分隔符时,此时连续的非空白分隔符会被作为多个分隔符。
2.2 命令替换
2.3 读取输入
如果修改了 IFS 变量值,可以简单地通过 unset IFS
恢复其默认值。
结语
水平有限,如文中有不恰当的地方,还请指正~
标签:分割,shell,IFS,echo,分隔符,字符串 From: https://blog.csdn.net/OMEMSTMATM/article/details/143377575