How can I join elements of an array in Bash?

2019-01-01 07:38发布

If I have an array like this in Bash:

FOO=( a b c )

How do I join the elements with commas? For example, producing a,b,c.

标签: arrays bash
27条回答
琉璃瓶的回忆
2楼-- · 2019-01-01 08:26

This approach takes care of spaces within the values, but requires a loop:

#!/bin/bash

FOO=( a b c )
BAR=""

for index in ${!FOO[*]}
do
    BAR="$BAR,${FOO[$index]}"
done
echo ${BAR:1}
查看更多
与君花间醉酒
3楼-- · 2019-01-01 08:28

Use perl for multicharacter separators:

function join {
   perl -e '$s = shift @ARGV; print join($s, @ARGV);' "$@"; 
}

join ', ' a b c # a, b, c

Or in one line:

perl -le 'print join(shift, @ARGV);' ', ' 1 2 3
1, 2, 3
查看更多
泛滥B
4楼-- · 2019-01-01 08:29

Here's a 100% pure Bash function that does the job:

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}"
}

Look:

$ 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


$

This preserves even the trailing newlines, and doesn't need a subshell to get the result of the function. If you don't like the printf -v (why wouldn't you like it?) and passing a variable name, you can of course use a global variable for the returned string:

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}"
}
查看更多
有味是清欢
5楼-- · 2019-01-01 08:30

In case the elements you want to join is not an array just a space separated string, you can do something like this:

foo="aa bb cc dd"
bar=`for i in $foo; do printf ",'%s'" $i; done`
bar=${bar:1}
echo $bar
    'aa','bb','cc','dd'

for example, my use case is that some strings are passed in my shell script and I need to use this to run on a SQL query:

./my_script "aa bb cc dd"

In my_script, I need to do "SELECT * FROM table WHERE name IN ('aa','bb','cc','dd'). Then above command will be useful.

查看更多
唯独是你
6楼-- · 2019-01-01 08:32
$ set a 'b c' d

$ history -p "$@" | paste -sd,
a,b c,d
查看更多
若你有天会懂
7楼-- · 2019-01-01 08:32

This isn't all too different from existing solutions, but it avoids using a separate function, doesn't modify IFS in the parent shell and is all in a single line:

arr=(a b c)
printf '%s\n' "$(IFS=,; echo "${arr[*]}")"

resulting in

a,b,c
查看更多
登录 后发表回答