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:18

If you build the array in a loop, here is a simple way:

arr=()
for x in $(some_cmd); do
   arr+=($x,)
done
arr[-1]=${arr[-1]%,}
echo ${arr[*]}
查看更多
梦该遗忘
3楼-- · 2019-01-01 08:19

Yet another solution:

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

echo $bar

Edit: same but for multi-character variable length separator:

#!/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
查看更多
泪湿衣
4楼-- · 2019-01-01 08:19

Shorter version of top answer:

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

Usage:

joinStrings "$myDelimiter" "${myArray[@]}"
查看更多
爱死公子算了
5楼-- · 2019-01-01 08:19

Here's one that I think is POSIX-compatible:

join_by() {
    # Usage:  join_by "||" a b c d
    local arg arr=() sep="$1"
    shift
    for arg in "$@"; do
        if [ 0 -lt "${#arr[@]}" ]; then
            arr+=("${sep}")
        fi
        arr+=("${arg}") || break
    done
    printf "%s" "${arr[@]}"
}
查看更多
心情的温度
6楼-- · 2019-01-01 08:21

Thanks @gniourf_gniourf for detailed comments on my combination of best worlds so far. Sorry for posting code not thoroughly designed and tested. Here is a better try.

# join with separator
join_ws() { local d=$1 s=$2; shift 2 && printf %s "$s${@/#/$d}"; }

This beauty by conception is

  • (still) 100% pure bash ( thanks for explicitly pointing out that printf is a builtin as well. I wasn't aware about this before ... )
  • works with multi-character delimiters
  • more compact and more complete and this time carefully thought over and long-term stress-tested with random substrings from shell scripts amongst others, covering use of shell special characters or control characters or no characters in both separator and / or parameters, and edge cases, and corner cases and other quibbles like no arguments at all. That doesn't guarantee there is no more bug, but it will be a little harder challenge to find one. BTW, even the currently top voted answers and related suffer from such things like that -e bug ...

Additional examples:

$ join_ws '' a b c
abc
$ join_ws ':' {1,7}{A..C}
1A:1B:1C:7A:7B:7C
$ join_ws -e -e
-e
$ join_ws $'\033[F' $'\n\n\n'  1.  2.  3.  $'\n\n\n\n'
3.
2.
1.
$ join_ws $ 
$
查看更多
回忆,回不去的记忆
7楼-- · 2019-01-01 08:21

Perhaps I'm missing something obvious, since I'm a newb to the whole bash/zsh thing, but it looks to me like you don't need to use printf at all. Nor does it get really ugly to do without.

join() {
  separator=$1
  arr=$*
  arr=${arr:2} # throw away separator and following space
  arr=${arr// /$separator}
}

At least, it has worked for me thus far without issue.

For instance, join \| *.sh, which, let's say I'm in my ~ directory, outputs utilities.sh|play.sh|foobar.sh. Good enough for me.

EDIT: This is basically Nil Geisweiller's answer, but generalized into a function.

查看更多
登录 后发表回答