如果我在Bash中有一个这样的数组:

FOO=( a b c )

如何用逗号连接元素?例如,生成a b c。


当前回答

还有另一个解决方案:

#!/bin/bash
foo=('foo bar' 'foo baz' 'bar baz')
bar=$(printf ",%s" "${foo[@]}")
bar=${bar:1}

echo $bar

编辑:相同,但用于多字符可变长度分隔符:

#!/bin/bash
separator=")|(" # e.g. constructing regex, pray it does not contain %s
foo=('foo bar' 'foo baz' 'bar baz')
regex="$( printf "${separator}%s" "${foo[@]}" )"
regex="${regex:${#separator}}" # remove leading separator
echo "${regex}"
# Prints: foo bar)|(foo baz)|(bar baz

其他回答

支持多字符分隔符的100%纯Bash函数是:

function join_by {
  local d=${1-} f=${2-}
  if shift 2; then
    printf %s "$f" "${@/#/$d}"
  fi
}

例如,

join_by , a b c #a,b,c
join_by ' , ' a b c #a , b , c
join_by ')|(' a b c #a)|(b)|(c
join_by ' %s ' a b c #a %s b %s c
join_by $'\n' a b c #a<newline>b<newline>c
join_by - a b c #a-b-c
join_by '\' a b c #a\b\c
join_by '-n' '-e' '-E' '-n' #-e-n-E-n-n
join_by , #
join_by , a #a

上面的代码基于@gniourf_gniourf、@AdamKatz、@MattCowell和@x-yuri的想法。它使用选项errexit (set -e)和nounset (set -u)。

或者,一个更简单的只支持单个字符分隔符的函数是:

function join_by { local IFS="$1"; shift; echo "$*"; }

例如,

join_by , a "b c" d #a,b c,d
join_by / var local tmp #var/local/tmp
join_by , "${FOO[@]}" #a,b,c

这个解决方案是基于Pascal Pilz最初的建议。

前面提出的解决方案的详细说明可以在“如何在bash脚本中连接()数组元素”中找到,这是meleu在dev.to上发表的一篇文章。

$ set a 'b c' d

$ history -p "$@" | paste -sd,
a,b c,d

通过重用@doesn't matters的解决方案,但通过避免${:1}的替换和中间变量的需要,使用了一个语句。

echo $(printf "%s," "${LIST[@]}" | cut -d "," -f 1-${#LIST[@]} )

printf有'格式字符串被重复使用,以满足参数。,这样字符串的连接就被记录下来了。然后诀窍是使用LIST长度来切割最后一个sperator,因为cut将只保留LIST的长度作为字段计数。

我将数组作为字符串回显,然后将空格转换为换行,然后使用粘贴将所有内容连接到一行,如下所示:

tr " " "\n" <<< "$FOO" |粘贴-sd, -

结果:

a, b, c

对我来说,这似乎是最快最干净的!

我相信这是最短的解决方案,正如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