我正在阅读有关bash internal variables的内容,并遇到了这个IFS
示例:
output_args_one_per_line()
{
for arg
do
echo "[$arg]"
done # ^ ^ Embed within brackets, for your viewing pleasure.
}
CASE1
IFS=" "
var=" a b c "
output_args_one_per_line $var
#OUTPUT
# [a]
# [b]
# [c]
CASE2
IFS=:
var=":a::b:c:::" # Same pattern as above
CASE2
# but substituting ":" for " " ...
output_args_one_per_line $var
# []
# [a]
# []
# [b]
# [c]
# []
# []
现在,根据我的理解,IFS
的值是否为默认值\t\n
而不是前导空格和尾随空格。因此,对于case1 bash,将var
视为a b c
,因此输出。
对于case2,根据我bash,var
将|a||b|c|||
视为|
为space
。我用
Noob@Noob:~/tmp$ IFS=$':' FOO=$":a::b:c:::"; echo $FOO $'x'
a b c x
所以,我对案例2的预期输出是
# []
# [a]
# []
# []
# [b]
# [c]
# []
# []
# []
那么,有人可以在内部向我解释bash在案例2中如何处理var
以及我在理解的地方出错了。
答案 0 :(得分:3)
您的声明(已编辑为使用':'代替'|'):
对于case2,根据我bash将var视为:a :: b:c ::: treat:as space here。
是假的。 IFS
会导致bash
将:
视为单词分隔符,而不是空格。不要因为空格是默认字分隔符而混淆两者。
答案 1 :(得分:2)
:
是分隔符。 a:b
分为a
和b
,两者之间没有任何内容。在您预期的行为中,您将如何编码以下内容?
[a]
[]
[b]
唯一奇怪的是最后没有三个空字符串。这可能是因为
由于没有值的参数的扩展而产生的不带引号的隐式空参数将被删除。
答案 2 :(得分:2)
在案例2 上,您":a::b:c:::"
与IFS=:
所以你正在做的是分裂每个符合:
所以,从字符串的开头到第一个:
,你有":
这是没有,因此[]
从第一个:
到下一个:
您有:a:
这是a
,因此[a]
从那里到下一个:
你有::
这是没有,因此[]
从那里到下一个:
你有:b:
这是b
,因此[b]
从那里到下一个:
你有:c:
这是c
,因此[c]
从那里到下一个:
你有::
这是没有,因此[]
从那里到下一个:
你有::"
这是没有,因此[]
所以你得到了那个结果..
正如@Mark Reed在评论中提到的,你可以使用printf
与bash -x
一起得到:
$ bash -x
$ IFS=':'; var=':a::b:c:::'; printf "[%s]\n" $var
[12]+ IFS=:
[12]+ var=:a::b:c:::
[12]+ printf '[%s]\n' '' a '' b c '' '' # notice this
[]
[a]
[]
[b]
[c]
[]
[]
答案 3 :(得分:1)
原因很简单:
IFS=" "
var=" a b c "
output_args_one_per_line $var
这意味着使用此参数调用output_args_one_per_line
:
output_args_one_per_line a b c
在解析命令行时,BASH将删除额外的空格,因此实际调用将使用
output_args_one_per_line a b c
即。多个空格合并为一个,a
之前的空格将成为命令和第一个参数之间的空格。
这意味着在应用 IFS
之前,空格将消失。这也意味着你不能写
IFS=:
output_args_one_per_line:$var
命令后必须有空格,而不是单词分隔符。
您可以使用set -x
运行脚本以查看跟踪输出(即BASH如何扩展行)。
在第二种情况下,单词分隔符不是空格字符,因此命令和第一个参数之间必要的空格不与参数合并,行变为
output_args_one_per_line :a::b:c:::
唯一奇怪的是输出应该是c
之后的三个空参数,但这可能是因为删除了空尾随参数(就像BASH在参数之后删除空格一样)。这是另一个奇怪的输出:
IFS=:
var=":a::b:c::: " # Blank after C
> output_args_one_per_line $var
[]
[a]
[]
[b]
[c]
[]
[]
[ ]
因此,如果var
在最后一个冒号之后确实包含任何内容,那么我们会得到缺少的参数。