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
.
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
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
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}
With re-use of @doesn't matters' solution, but with a one statement by avoiding the ${:1} substition and need of an intermediary variable.
echo $(printf "%s," "${LIST[@]}" | cut -d "," -f 1-${#LIST[@]} )
printf has 'The format string is reused as often as necessary to satisfy the arguments.' in its man pages, so that the concatenations of the strings is documented. Then the trick is to use the LIST length to chop the last sperator, since cut will retain only the lenght of LIST as fields count.
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.
printf solution that accept separators of any length (based on @doesn't matters answer)
#/!bin/bash
foo=('foo bar' 'foo baz' 'bar baz')
sep=',' # can be of any length
bar=$(printf "${sep}%s" "${foo[@]}")
bar=${bar:${#sep}}
echo $bar