Bash: 使用IFS将数组合并为字符串

3

有人可以解释一下这里正在发生什么吗?所有的内容都是在同一个shell中连续执行的。

$ array=(a b c)
$ echo "${array[*]}"
a b c

到目前为止,一切都很顺利。
$ IFS=/ echo "${array[*]}"
a b c

没问题,扩展发生在整行代码执行之前。

$ IFS=/ x="${array[*]}"
$ echo $x
a b c

我也是,扩展发生在先,x得到了那个值。

$ echo "${array[*]}"
a/b/c

但是${array[*]}已经被更改,并且这个更改是永久性的。
$ x="${array[*]}"
$ echo $x
a b c

好的,我认为这是正常的 - 在此赋值中,使用了原始默认的IFS值来扩展数组变量。

$ echo "${array[*]}"
a/b/c
$ 

但是这对我来说完全没有意义。首先,这里没有使用默认的IFS。其次,在IFS=/ x="${array[*]}"中,赋值x="${array[*]}"没有像之前那样影响${array[*]}的值。

2个回答

1
当你使用时:

IFS=/ echo "${array[*]}"

我会帮助您翻译相关编程内容,此处意为将IFS设置为echo命令的本地变量(虽然echo命令不使用IFS)。

当您使用以下命令时:

IFS=/ x="${array[*]}"

那么这是两个分开的变量赋值,一个是IFS,另一个是x,所以IFS现在被永久地更改为 /,正如@jaypal所提到的。

当你使用:

$ echo "${array[*]}"

当IFS的第一个字符被引用时,它会作为数组扩展的输出字段分隔符。

如果未被引用,则产生以空格分隔的字段:

$ echo ${array[*]}

Also, when you would use:

$ echo "${array[@]}"

然后每个数组元素都被扩展为单独的单词,因此输出字段分隔符未使用,因此它变成了单个空格。

是的,我明白了!这就是导致我的困惑的关键区别——当跟随一个命令时,赋值只在该命令中局部有效。当有两个赋值时,它们都对 shell 的其余部分有效。再加上一些引用混淆,以及 IFS 的值用于拆分未引用的 $IFS 本身,这造成了一个深刻的 WTF 瞬间 :D - ultracrepidarian

0

首先,为了解释混淆的来源,我将使用一些非常简单的情况。虽然我们将使用单个字符字符串进行操作,但我将使用适当的引用,尽管在此处不需要。

情况A:赋值后跟随一个命令。

$ x=y echo "$x"

$ echo "$x"

$ 

这里发生了两件事情:

  • 当跟随一个命令时,赋值只在该命令中局部有效。这就是为什么第二个echo "$x"返回一个空字符串。
  • 参数扩展先于赋值执行。这就是为什么第一个echo "$x"也返回一个空字符串。实际上,在这种情况下,x=y什么也没做。

情况B:同一行上的两个赋值。

$ x=y z="$x"
$ echo "$x"
y
$ echo "$z"
y
$ 

同样的两个点现在相反:

  • 两个赋值都对 shell 的剩余部分有效(或者直到取消为止)。
  • 参数扩展不会立即发生。第一个赋值被执行,结果用于第二个赋值。因此,xz 都设置为 y,并对 shell 的剩余部分有效。

数组、IFS 和引用。

这些也都起了作用,并且值得向不熟悉它们的人解释。然而,对我来说问题主要是关于赋值的,一旦弄清楚了这一点,其他所有事情都水到渠成了。请注意,IFS 的值适用于未引用的 $IFS 本身。因此,echo $IFS 总是返回一个空行:

$ IFS=BOO
$ echo $IFS

$ 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接