如果我在Bash中有一个这样的数组:
FOO=( a b c )
如何用逗号连接元素?例如,生成a b c。
如果我在Bash中有一个这样的数组:
FOO=( a b c )
如何用逗号连接元素?例如,生成a b c。
当前回答
这些解决方案中的许多(如果不是大多数的话)依赖于晦涩难懂的语法、耗费脑力的正则表达式技巧或对外部可执行文件的调用。我想提出一个简单的、只使用bash的解决方案,它非常容易理解,在性能方面只是稍微次优。
join_by () {
# Argument #1 is the separator. It can be multi-character.
# Argument #2, 3, and so on, are the elements to be joined.
# Usage: join_by ", " "${array[@]}"
local SEPARATOR="$1"
shift
local F=0
for x in "$@"
do
if [[ F -eq 1 ]]
then
echo -n "$SEPARATOR"
else
F=1
fi
echo -n "$x"
done
echo
}
例子:
$ a=( 1 "2 2" 3 )
$ join_by ", " "${a[@]}"
1, 2 2, 3
$
我想指出,任何使用/usr/bin/[或/usr/bin/printf的解决方案本质上都比我的解决方案慢,因为我使用100%纯bash。作为性能的一个例子,这里有一个演示,我创建了一个包含1,000,000个随机整数的数组,然后用逗号将它们全部连接起来,并计时。
$ eval $(echo -n "a=("; x=0 ; while [[ x -lt 1000000 ]]; do echo -n " $RANDOM" ; x=$((x+1)); done; echo " )")
$ time join_by , ${a[@]} >/dev/null
real 0m8.590s
user 0m8.591s
sys 0m0.000s
$
其他回答
结合所有最好的世界到目前为止与以下的想法。
# join with separator
join_ws() { local IFS=; local s="${*/#/$1}"; echo "${s#"$1$1$1"}"; }
这个小杰作是
100%纯bash(参数扩展,暂时不设置IFS,没有外部调用,没有printf…) 紧凑、完整和完美(适用于单字符和多字符限制符,适用于包含空格、换行符和其他shell特殊字符的限制符,适用于空分隔符) 高效(无子shell,无数组复制) 简单而愚蠢,但在某种程度上,也很漂亮,很有教育意义
例子:
$ join_ws , a b c
a,b,c
$ join_ws '' a b c
abc
$ join_ws $'\n' a b c
a
b
c
$ join_ws ' \/ ' A B C
A \/ B \/ C
awk -v sep=. 'BEGIN{ORS=OFS="";for(i=1;i<ARGC;i++){print ARGV[i],ARGC-i-1?sep:""}}' "${arr[@]}"
or
$ a=(1 "a b" 3)
$ b=$(IFS=, ; echo "${a[*]}")
$ echo $b
1,a b,3
我相信这是最短的解决方案,正如Benamin W.已经提到的:
(IFS=,; printf %s "${a[*]}")
想要添加,如果你使用zsh,你可以删除子shell:
IFS=, printf %s "${a[*]}"
测试:
a=(1 'a b' 3)
IFS=, printf %s "${a[*]}"
1,a b,3
现在我用的是:
TO_IGNORE=(
E201 # Whitespace after '('
E301 # Expected N blank lines, found M
E303 # Too many blank lines (pep8 gets confused by comments)
)
ARGS="--ignore `echo ${TO_IGNORE[@]} | tr ' ' ','`"
这是可行的,但是(在一般情况下)如果数组元素中有空格,将会严重破坏。
(对于那些感兴趣的人,这是一个围绕pep8.py的包装器脚本)
$ foo=(a "b c" d)
$ bar=$(IFS=, ; echo "${foo[*]}")
$ echo "$bar"
a,b c,d