问题
我正在编写一个bash脚本(版本4.3.48)。我有一个数组,并希望将所有条目连接为一个字符串。以下代码执行此类任务(但在某些情况下滞后):
declare -a array=(one two three)
echo "${array[@]}"
不幸的是我得到了这个输出,包括数组条目之间的空格:
one two three
但我真正需要的是:
onetwothree
的背景
我尽量避免使用for循环并自己连接它,因为我经常调用它(超过每秒)并且我猜这样的循环比使用内置函数要贵得多。 / p>
那么有关如何获得所需结果的建议吗?
答案 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}"; }