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

FOO=( a b c )

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


当前回答

下面是一个100%纯Bash函数,它可以完成这项工作:

join() {
    # $1 is return variable name
    # $2 is sep
    # $3... are the elements to join
    local retname=$1 sep=$2 ret=$3
    shift 3 || shift $(($#))
    printf -v "$retname" "%s" "$ret${@/#/$sep}"
}

看:

$ a=( one two "three three" four five )
$ join joineda " and " "${a[@]}"
$ echo "$joineda"
one and two and three three and four and five
$ join joinedb randomsep "only one element"
$ echo "$joinedb"
only one element
$ join joinedc randomsep
$ echo "$joinedc"

$ a=( $' stuff with\nnewlines\n' $'and trailing newlines\n\n' )
$ join joineda $'a sep with\nnewlines\n' "${a[@]}"
$ echo "$joineda"
 stuff with
newlines
a sep with
newlines
and trailing newlines


$

这甚至保留了末尾的换行符,并且不需要一个子shell来获得函数的结果。如果你不喜欢printf -v(为什么你不喜欢它?)并传递一个变量名,你当然可以为返回的字符串使用一个全局变量:

join() {
    # $1 is sep
    # $2... are the elements to join
    # return is in global variable join_ret
    local sep=$1 IFS=
    join_ret=$2
    shift 2 || shift $(($#))
    join_ret+="${*/#/$sep}"
}

其他回答

liststr=""
for item in list
do
    liststr=$item,$liststr
done
LEN=`expr length $liststr`
LEN=`expr $LEN - 1`
liststr=${liststr:0:$LEN}

这也可以处理结尾多余的逗号。我不是bash专家。只是我的2c,因为这更基本,更容易理解

顶部答案的简短版本:

joinStrings() { local a=("${@:3}"); printf "%s" "$2${a[@]/#/$1}"; }

用法:

joinStrings "$myDelimiter" "${myArray[@]}"
$ foo=(a "b c" d)
$ bar=$(IFS=, ; echo "${foo[*]}")
$ echo "$bar"
a,b c,d

x = $ {arr [*] / /,)

这是做这件事最短的方法。

的例子,

# ZSH:
arr=(1 "2 3" 4 5)
x=${"${arr[*]}"// /,}
echo $x  # output: 1,2,3,4,5

# ZSH/BASH:
arr=(1 "2 3" 4 5)
a=${arr[*]}
x=${a// /,}
echo $x  # output: 1,2,3,4,5

这个简单的单字符分隔符解决方案需要非posix模式。在POSIX模式下,元素仍然正确地连接,但IFS=,赋值变成永久的。

IFS=, eval 'joined="${foo[*]}"'

使用#!bash头在默认情况下以非posix模式执行,但为了帮助确保脚本以非posix模式运行,请在脚本开头添加set +o posix或shop -uo posix。


对于多字符分隔符,我建议使用带有转义和索引技术的printf解决方案。

function join {
    local __sep=${2-} __temp
    printf -v __temp "${__sep//%/%%}%s" "${@:3}"
    printf -v "$1" %s "${__temp:${#__sep}}"
}

join joined ', ' "${foo[@]}"

Or

function join {
    printf -v __ "${1//%/%%}%s" "${@:2}"
    __=${__:${#1}}
}

join ', ' "${foo[@]}"
joined=$__

这是基于里卡多加利的回答和我的建议。