16

I'd like

$ echo a{b,c,d}

to output a comma-separated list like

ab,ac,ad

instead of the usual output

ab ac ad

What's the easiest way to do that on the command line?

7

Assuming that the elements do not contain spaces, you could translate spaces to commas:

echo a{b,c,d} | tr ' ' ,

which produces:

ab,ac,ad

You can also use ranges with characters:

echo a{b..d} | tr ' ' ,

This is especially useful if you want a larger range.

13

It seems bash does not use $IFS to join the generated words. Another technique would be to store the generated words in an array and then $IFS will be in play:

I'm going to use a subshell so I don't alter this shell's IFS: pick one of

( words=( a{b,c,d} ); IFS=,; echo "${words[*]}" )
( set -- a{b,c,d}; IFS=,; echo "$*" )

That emits the comma-separates string to stdout. If you want to capture it:

joined=$( set -- a{b,c,d}; IFS=,; echo "$*" )
  • It does not join the generated words at all. That's the whole point, it expands to separate words. – Stéphane Chazelas Aug 10 '18 at 9:20
3

I am sure there are many ways to accomplish this. Here is one method:

echo a{b,c,d} | sed 's/ /,/g'
2

Expand the elements like you showed and then loop over them, adding the comma to all but the first iteration:

for i in a{b,c,d}; do
  u="${u:+$u, }$i"
done
echo "$u"

Result:

ab, ac, ad

See bash parameter substitution.

1

Here's a bash-only solution.

(IN=$(echo a{b,c,d}); echo ${IN// /,})
# ab,ac,ad

The part before the semicolon assigns ab ac ad to the variable IN and the second part uses search and replace to change all spaces to commas. The // means all matches, not just the first.

Do it all in a subshell (the enclosing parentheses) to not pollute your namespace.

1

It's worth noting that in many contexts, a trailing comma is acceptable in such a list. IF a trailing comma is acceptable, the easiest way to handle the substitution is printf:

some-command "$(printf %s, a{b,c,d} )"

(Where some-command is a command that runs on a comma separated list, and doesn't care about a trailing comma.)

Actually, even if you must not have a trailing comma you can use printf; you just need to specify the number of arguments you expect, which makes it clumsier for very long lists:

some-command "$(printf %s,%s,%s a{b,c,d} )"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.