Reputation: 565
I have a file like this:
user$ cat -t file
0.1^I^I^I0.2
I wish to edit the file so that every time two consecutive tabs appear, the characters "NA" are inserted in the middle of the two tabs. The number of consecutive tab characters that could appear is arbitrary (in this example there are three tabs in succession but it could be two or more than three).
I've tried doing this with sed (BSD sed):
user$ cat -t <(sed $'s/\t\t/\tNA\t/g' file)
But this only inserts the desired characters in the middle of the first two consecutive tabs yielding this output:
0.1^INA^I^I0.2
I also need the characters to be inserted in the middle of the second pair of consecutive tabs in order to get this output:
0.1^INA^INA^I0.2
Would prefer to use sed for this, but other tools such as awk or perl could be used.
Upvotes: 2
Views: 111
Reputation: 113844
The problem is that sed doesn't do overlapping matches. We need to repeat the substitution until all matches have been made. Thus, try:
$ cat -t <(sed ':a; s/\t\t/\tNA\t/g; ta' file)
0.1^INA^INA^I0.2
Consider \t\t\t
. The substitution command matches the first \t\t
and replaces it with \tNA\t
. The problem is that, with the g
option, the next substitution can only start after those first two tabs. Overlapping substitutions are not supported. That is why we need to add the label and branching commands as above.
:a
This creates a label a
.
s/\t\t/\tNA\t/g
This does the substitution you want.
ta
If the preceding substitution command successfully made a substitution, this tells sed to jump back to label a
. Consequently, the substitution command will be repeated as many times as necessary.
With thanks to mikekatz45, the BSD version is:
cat -t <(sed -e :a -e $'s/\t\t/\tNA\t/g' -e ta file)
Note that, while the $'...'
construct is not POSIX, it will work under bash
, ksh
, and zsh
.
Upvotes: 3
Reputation: 52419
Perl version using a 0-width lookahead to make the matches not overlap:
$ echo -e "0.1\t\t\t0.2" | perl -pe 's/\t(?=\t)/\tNA/g' | cat -t
0.1^INA^INA^I0.2
Or for modifying a file in-place:
$ perl -pi -e 's/\t(?=\t)/\tNA/g' blah.txt
Upvotes: 0