1

Given a string of characters ,,a,,,b,,,, I want to impose the character - at the beginning, if no character is preceded comma, and between every comma that has no character. Meaning the result is -,-,a,-,-,b,-,-,-,-. Now, I already tried:

echo ",,a,,,b,,,," | sed 's/,/,-/g' | sed 's/-\([^,]\)/\1/g' | sed 's/^,/-&/g'

resulting in: -,-,a,-,-,b,-,-,-,-

But the problem is, invoking sed 3 times is inefficient in very long iterations. Is there a way to do this with sed, probably using regex, or any other tool invoking it once?

0
1

One way to do it in sed would be to use a loop:

$ echo ",,a,,,b,,,," | sed ':a; s/\(^\|,\)\(,\|$\)/\1-\2/; ta'
-,-,a,-,-,b,-,-,-,-

If your version supports extended regular expressions you can simplify it to a more readable

sed -E ':a; s/(^|,)(,|$)/\1-\2/; ta'

An alternate way to do it in perl, splitting into comma-separated fields and then mapping empty fields to hyphens:

perl -anle 'print join ",", map { $_ ? $_ : "-" } split(",", $_, -1)'

(The additional -1 argument to the split forces trailing empty fields to be included).

3
(echo ,,a,,,b,,,,; echo a,,b) | perl -pe 's/(^|,)\K(?=(,|$))/-/g' 
-,-,a,-,-,b,-,-,-,-
a,-,b

I guess I should learn sed one of these years.

2
  • Try this tutorial one of these years. ;) – Wildcard May 15 '16 at 6:13
  • Thank you very much for your answer. But when I input 'a,,a,,,b,,,,' it gives '-a,-,a,-,-,b,-,-,-,-'. How do I avoid inputting - when there is a letter before the first ,? – mark_infinite May 15 '16 at 13:45
1
echo ",,a,,,b,,,," |
  awk -v 'FS=,' -v 'OFS=,' '{for (i=1; i<=NF; i++) sub(/^$/,"-",$i); print};'
0
$ echo ',,a,,,b,,,,' | sed 's/\(\([^,]\+,\)*\),/\1-,/g; s/\(^\|,\)$/\1-/'
-,-,a,-,-,b,-,-,-,-

The second expression (the s/\(^\|,\)$/\1-/) is necessary only because sed seems to stop matching when it has reached the end of the pattern space, even though it could still match a $ if the only expression were s/\(\([^,]\+,\)*\)\(,\|$\)/\1-\3/g.

Of course, sed -E makes it a bit more readable, but otherwise equivalent:

sed -E 's/(([^,]+,)*),/\1-,/g; s/(^|,)$/\1-/'

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.