首页 > 解决方案 > 为什么用`printf`加入数组会在终端和脚本中给出不同的结果?

问题描述

我正在尝试编写一个脚本,其中涉及打印带有分隔符的数组。不幸的是,在printf命令行中输入的命令在作为脚本运行时不起作用。似乎 bash 和 zsh 处理事情的方式也不同。

这给出了预期的输出,如果我像这样直接粘贴到终端中,它就可以工作:

➜  ~ array=()
array+=a
array+=b
array+=c
array+=d
printf -v tmp '%s\n' "${array[@]}"
echo "$tmp"
a
b
c
d

但是,当作为脚本运行时,输出不是我想要的:

➜  ~ echo 'array=()
array+=a
array+=b
array+=c
array+=d
printf -v tmp '%s\n' "${array[@]}"
echo "$tmp"' > test1.sh
➜  ~ bash test1.sh 
abcdn

然后我记得 zsh 是我的默认 shell,所以我尝试使用 zsh 显式运行它。结果更接近我想要的(每个数组元素之间都有一些东西),但仍然不是我粘贴到终端时得到的结果。为什么\\n这种情况下忽略 in ?

➜  ~ zsh test1.sh
anbncndn

此外,是否有一个方便的表格来说明基本命令(如 shell 之间以及脚本与终端之间)的主要echo区别printf

编辑:

我注意到我的示例存在缺陷,因为当我创建脚本test.sh文件时,回显在 n 之前省略了反斜杠。

➜  ~ echo '
array=()
array+=a
array+=b
array+=c
array+=d
printf -v tmp '%s\n' "${array[@]}"
echo "$tmp"
'

array=()
array+=a
array+=b
array+=c
array+=d
printf -v tmp %sn "${array[@]}"
echo "$tmp"

但让我失望的是,它zsh -c表现出同样的行为。它是否也去掉了反斜杠?

➜  ~ zsh -c 'array=()
array+=a
array+=b
array+=c
array+=d
printf -v tmp '%s\n' "${array[@]}"
echo "$tmp"'
anbncndn

编辑 2:在这些情况下,转义字符都起作用。三个前面的反斜杠又变成了一个很好的换行符。

zsh -c 'array=()
array+=a
array+=b
array+=c
array+=d
printf -v tmp '%s\\\\n' "${array[@]}"
echo "$tmp"'
a
b
c
d

EDIT3:所以脚本中的转义与'-c'不同

剧本:

#!/bin/zsh
array=()
array+=a
array+=b
array+=c
array+=d
printf -v tmp '%s\\n' "${array[@]}"
echo "$tmp"

结果:

➜  ~ zsh test.sh     
a
b
c
d

标签: arraysbashshellprintfzsh

解决方案


zsh处理数组的方式不同于bash. 在zsh(您的交互式外壳)中,array+=b确实将字符串附加b为新的数组元素。

但是,在bash中,相同的命令仅将字符串附加b到数组的第一个元素;要附加一个新元素,您需要使用array+=(b).


推荐阅读