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

时间:2018-02-22 19:50:20

标签: arrays bash performance concatenation

问题

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

declare -a array=(one two three)
echo "${array[@]}"

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

one two three

但我真正需要的是:

onetwothree


背景

我尽量避免使用for循环并自己连接它,因为我经常调用它(超过每秒)并且我猜这样的循环比使用内置函数要贵得多。 / p>

那么有关如何获得所需结果的建议吗?

2 个答案:

答案 0 :(得分:5)

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

printf %s "${array[@]}" $'\n'

(这是因为shell的printf不断重复模式,直到参数全部用完为止。)

答案 1 :(得分:2)

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

$ 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

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

$ array=( one two three )
$ declare  -p array
declare -a array='([0]="one" [1]="two" [2]="three")'

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

$ (IFS=; echo "${array[*]}")
onetwothree

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

$ joined=$(IFS=; echo "${array[*]}"); echo "$joined"
onetwothree

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

$ printf "%s" "$IFS" | od -c
0000000      \t  \n
0000003

如果性能是目标,并且您希望避免产生子shell,请使用函数:

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

bash版本早于4.3,使用间接变量而不是nameref

$ concat_array() { local tmp="${1}[*]"; local IFS=; echo "${!tmp}"; }