Bash连接数组条目,中间没有空格

wei*_*ith 2 arrays bash performance concatenation

问题

我正在编写一个bash脚本(版本4.3.48).我有一个数组,并希望将所有条目连接为一个字符串.以下代码执行此类任务(但在某些情况下滞后):

declare -a array=(one two three)
echo "${array[@]}"
Run Code Online (Sandbox Code Playgroud)

不幸的是我得到了这个输出,包括数组条目之间的空格:

one two three
Run Code Online (Sandbox Code Playgroud)

但我真正需要的是:

onetwothree
Run Code Online (Sandbox Code Playgroud)


背景

我试图避免使用for循环并自己连接它,因为我经常调用它(超过每秒)并且我猜这样的循环比使用内置函数昂贵得多.

那么任何建议如何获得所需的结果?

ric*_*ici 6

printf 为您提供了更多的格式控制,它也是一个内置的bash:

printf %s "${array[@]}" $'\n'
Run Code Online (Sandbox Code Playgroud)

(这是有效的,因为shell printf继续重复模式,直到参数全部用完为止.)


gle*_*man 6

首先,这是初始化数组的错误方法:

$ declare -A array=( one two three )
bash: array: one: must use subscript when assigning associative array
bash: array: two: must use subscript when assigning associative array
bash: array: three: must use subscript when assigning associative array
Run Code Online (Sandbox Code Playgroud)

declare -A用于关联数组。就这样做

$ array=( one two three )
$ declare  -p array
declare -a array='([0]="one" [1]="two" [2]="three")'
Run Code Online (Sandbox Code Playgroud)

您想使用*下标而不是@. 使用数组的第一个字符连接数组元素IFS。如果您不需要任何分隔符,请将空字符串分配给 IFS。由于很多事情都依赖于 IFS,我通常使用子 shell 来包含修改:

$ (IFS=; echo "${array[*]}")
onetwothree
Run Code Online (Sandbox Code Playgroud)

要将结果分配给变量,这是通常的命令替换语法:

$ joined=$(IFS=; echo "${array[*]}"); echo "$joined"
onetwothree
Run Code Online (Sandbox Code Playgroud)

我们可以看到这个 shell 中的 IFS 值(空格、制表符、换行符)没有变化:

$ printf "%s" "$IFS" | od -c
0000000      \t  \n
0000003
Run Code Online (Sandbox Code Playgroud)

如果性能是一个目标并且您想避免生成子shell,请使用函数:

$ concat_array() { local -n a=$1; local IFS=; echo "${a[*]}"; }
$ concat_array array
onetwothree
Run Code Online (Sandbox Code Playgroud)

对于 4.3 之前的 bash 版本,使用间接变量而不是 nameref

$ concat_array() { local tmp="${1}[*]"; local IFS=; echo "${!tmp}"; }
Run Code Online (Sandbox Code Playgroud)