Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/299.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在本例中,bash IFS是如何工作的?_Bash_Ifs - Fatal编程技术网

在本例中,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
。然后从该点到下一个met
IFS
,等等。。像
::
这样的字符串将返回
[]
,这是空字符串,因为从第一个
到下一个
之间没有任何内容,但会发生拆分。@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]
[]
[]
[ ]