在本例中,bash IFS是如何工作的?
我正在阅读并偶然发现了以下在本例中,bash IFS是如何工作的?,bash,ifs,Bash,Ifs,我正在阅读并偶然发现了以下IFS示例: output_args_one_per_line() { for arg do echo "[$arg]" done # ^ ^ Embed within brackets, for your viewing pleasure. } 案例1 IFS=" " var=" a b c " output_args_one_per_line $var #OUTPUT # [a] # [b] # [c] 案例2 IFS=:
IFS
示例:
output_args_one_per_line()
{
for arg
do
echo "[$arg]"
done # ^ ^ Embed within brackets, for your viewing pleasure.
}
案例1
IFS=" "
var=" a b c "
output_args_one_per_line $var
#OUTPUT
# [a]
# [b]
# [c]
案例2
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
,那么前导和尾随的空格将被删除。因此,对于案例1,bash将var
视为abc
,因此输出
对于案例2,根据我的说法,bash在这里将var
视为|a | | b | c | | |
视为空格
。我用电脑检查了一下
Noob@Noob:~/tmp$ IFS=$':' FOO=$":a::b:c:::"; echo $FOO $'x'
a b c x
因此,我对案例2的预期输出是
# []
# [a]
# []
# []
# [b]
# [c]
# []
# []
# []
那么,有人能在内部向我解释一下bash在案例2中是如何处理var的,以及我的理解中哪里出错了。
:
是分隔符<代码>a:b分为a
和b
,两者之间没有任何内容。在您预期的行为中,您将如何编码以下内容
[a]
[]
[b]
唯一奇怪的是结尾没有三个空字符串。这可能是因为
由于扩展没有值的参数而导致的未加引号的隐式空参数将被删除
在案例2中,您有”:a::b:c::“
和如果=:
因此,您要做的是在每个met中拆分字符串
:
因此,从字符串的开头到第一个:
您就有了“:
它什么都不是,因此
[]
从第一个:
到下一个:
您拥有: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]
[]
[]
您的索赔(编辑为使用“:”而不是“|”):
对于案例2,根据我的说法,bash在这里将var视为:a::b:c::treat:作为空格
这是错误的
IFS
导致bash
将:
视为单词分隔符,而不是空格。不要仅仅因为空格是默认的单词分隔符就将两者混淆。原因很简单:
IFS=" "
var=" a b c "
output_args_one_per_line $var
这意味着使用此参数调用output\u args\u one\u per\u line
:
在解析命令行时,BASH将删除额外的空白,因此实际调用将使用
output_args_one_per_line a b c
i、 e.将多个空格合并为一个空格,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
在最后一个冒号之后确实包含任何内容,我们将得到缺少的参数。OT:output\u args\u one\u per\u line函数可以替换为printf”[%s]\n“$var
查看bash-x
展开var
时显示的拆分。请参阅我答案的编辑。如果我理解正确,则a::b
将被视为a(空格)(空词)b,这将导致a[]b。你能详细解释一下这件奇怪的事吗?因为我是一个巴什努伯,没有一个例子我对官方文件不太了解。你从开始到下一个遇到IFS
。然后从该点到下一个metIFS
,等等。。像::
这样的字符串将返回[]
,这是空字符串,因为从第一个:
到下一个:
之间没有任何内容,但会发生拆分。@Noob-在预期的输出中,您声称a::b
应该在a
和b
之间有两个空字符串,当它真的只有一个时。@c00kiemon5ter:谢谢,非常有用的解释。删除尾随的null参数(但不是前导参数)来自POSIX标准的措辞。据报道,委员会对此进行了激烈的辩论,在许多关心这类事情的人中,这是一个不受欢迎的决定。但它至少在不同的shell(ksh、{d、}ash、zsh等)中是一致的。这只是你必须解释的其中一个怪癖。你是对的,我在这里说错了。我真正的意思是用空格作为分隔符将bash更改为a:b
。
IFS=:
var=":a::b:c::: " # Blank after C
> output_args_one_per_line $var
[]
[a]
[]
[b]
[c]
[]
[]
[ ]