4

I have a line of text like:

value,value,,,value,value

I want the two empty values to be replaced with a different value. Something like:

value,value,hello,hello,value,value

I'm currently trying something like:

sed -e 's/^,/hello,/' -e 's/,$/,hello/' -e 's/,,/,hello,/g'

That catches blank values at the beginning, end and the middle. BUT, it doesn't catch two consecutive blank values in a row. How can I update the regular expression patterns so that an indefinite number of consecutive blank values can appear in the middle?

3
  • Sed doesn't support lookaheads or behinds, right. That makes this harder. Are any other regex flavors an option in your situation? Commented Jun 21, 2011 at 20:36
  • man sed says I can use --regexp-extended: use extended regular expressions in the script. Commented Jun 21, 2011 at 20:44
  • The solution doesn't have to use sed either. Any commonly available tool will do (i.e. installed by default on most distros). Commented Jun 21, 2011 at 20:49

3 Answers 3

5

What about this perl one-liner:

echo ',value,,,value,' | perl -pe 's/^(?=,)|(?<=,)(?=,|$)/hello/g'
# hello,value,hello,hello,value,hello
Sign up to request clarification or add additional context in comments.

5 Comments

Getting close, but it fails in one scenario I have. The line has four fields and all are empty: ,,,. Your perl produces hello,,hello,hello
@Steve Prentice: I think I spotted the bug and updated the one-liner. Let me know how it goes.
Glad I could help. Btw, turns out, you don't need captures at all. Check the updated version.
I'm a bit confused, whats the first backreference for? Ok you edited it... no more references :-) this is magic
Hehe, page reload helps at times ;) Btw everyone, I just made another tiny change to make it more compact. Last edit this one! (hopefully ;)
2

I don't think you can do it with a single substitute command, since Sed only replaces non-overlapped occurrences of your pattern. This ugly hack could work, but requires you to prevent one more character (I choosed ';') in your values :

$ echo 'value,value,,,value,value' | sed -r 's/,/,;/g;s/(^|;)(,|$)/\1hello\2/g;s/,;/,/g'
value,value,hello,hello,value,value

4 Comments

+1 Clever. So, you replace every , with ,;, do some magic, and then restore the delimiters. It works, but I'm going to wait on accepting as the answer because I hope there is a less ugly way to do it.
Well, you could also perform your substitution twice, like this: echo 'value,value,,,value,value' | sed -r 's/(^|,)(,|$)/\1hello\2/g;s/(^|,)(,|$)/\1hello\2/g' But that's ugly too :)
+1 for making it happen with sed when the "it doesn't have to be sed" part came up after your answer. And some seds will want -E rather than -r for this.
I actually like that approach. :) Each one catches every other one.
1

Other perl one-liners:

perl -we '$_=<>; while(s/,,/,hello,/) {}; print;'  value.txt

perl -we 'print join ",", map { $_ || 'hello' } split /,/, <>;' value.txt

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.