3

我正在阅读有关bash 内部变量的信息,并遇到了以下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前导和尾随空格将被删除。因此,对于 case1 bash vara 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]
# []
# []
# []

那么,有人可以在内部向我解释 bashvar在案例 2 中的处理方式以及我的理解哪里出错了。

4

4 回答 4

3

您的声明(编辑为使用“:”而不是“|”):

根据我的案例 2,bash 将 var 视为 :a::b:c::: 将 : 视为空格。

是假的。IFS导致bash:其视为单词分隔符,而不是空格。不要仅仅因为空格是默认的单词分隔符而将两者混淆。

于 2012-10-17T12:46:27.047 回答
2

:是分隔符。a:b分为aand b,中间没有。在您预期的行为中,您将如何编码以下内容?

[a]
[]
[b]

唯一奇怪的是最后没有三个空字符串。这可能是因为

不带引号的隐式空参数由没有值的参数的扩展产生,被删除。

于 2012-10-17T11:41:40.420 回答
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]
[]
[]
于 2012-10-17T11:52:50.767 回答
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在最后一个冒号之后确实包含任何内容,我们会得到缺少的参数。

于 2012-10-17T15:08:44.380 回答