Reputation: 7608
Say we have a row in CSV that look like so:
|Foo|,,,,,,,,|Bar|,,,,,
Where |
is out encapsulator, and ,
is out delimiter (as you might expect).
But say you have some code that needs to have these empty fields filled in, and instead you want to transform this row into something like this:
|Foo|,||,||,||,||,||,||,||,|Bar|,||,||,||,||,
(We can deal with the trailing comma later) I have tried to use this sed command over this CSV to get the desired result:
sed 's/,,/,||,/g'
However, the regex patter ,,
is not zero width, so as it scans over the line, it moves two along, even though we've only dealt with one field. The result is something like this:
|Foo|,||,,||,,||,,||,|Bar|,||,,||,,
The issue is that when we get this far in the substitution:
|Foo|,||,,,,,,,|Bar|,,,,,
We've already 'dealt with' the commas around our ||
, and we move onto the next pair after the last comma we regexed, which doesn't involve the last one of ,||,
.
How can I make this substitution using sed?
Upvotes: 2
Views: 645
Reputation: 31548
with awk we can do like this
awk '{while(i<2){gsub(",,",",||,");i++}}1' temp.txt
Upvotes: 1
Reputation: 85775
A more elegant way is to use conditional branching:
$ sed ':a;s/,,/,||,/;ta' <<< '|Foo|,,,,,,,,|Bar|,,,,,'
|Foo|,||,||,||,||,||,||,||,|Bar|,||,||,||,||,
From man sed
:
t label
If a s/// has done a successful substitution since the last input line was read and since the last t or T command, then branch to label; if label is omitted, branch to end of script.
Upvotes: 1
Reputation: 9962
A quick solution is to just repeat the substitution:
sed 's/,,/,||,/g;s/,,/,||,/g'
Upvotes: 1