I'm practising sed command using regex but the results are not as expected. I'm using terminal on mac Sierra. This is the input data:
Mark watermellons 12
Robert pears 4
Terry oranges 9
Lisa peaches 7
Susy oranges 12
Mark grapes 39
Anne mangoes 7
Greg pineapples 3
Oliver rockmellons 2
Betty limes 14
I'm trying to swap first and second column. I used this command:
sed 's/\(.+\) \(.+\) /\2 \1/ ' file.txt
This command is returning the same input. However when I use,
sed 's/\(.*\) \(.*\) /\2 \1 /' file.txt
the columns are getting swapped. why "+" is not matching since atleast one character is present in each row.
Also, when I use
sed 's/\(.*\) \(.*\)/\2 \1 /' file.txt
The first parenthesis is capturing first two columns and second one last column,why the first parenthesis is not capturing first column?
The problem is not about your understanding of regular expressions and greedy matching and whatnot. The problem is simply that the +
is not implemented in the example uses in the question.
In sed
, by default, +
does not mean "one or more of the previous symbol" as you might be used to it from other regex grammars.
To make this work in BSD sed
(as you are on OSX),
you need to enable extended regular expressions with -E
,
and also change the capturing group syntax:
sed -E 's/(.+) (.+) /\2 \1/ ' file.txt
Also note that +
is basically just a shortcut,
so you can always write it the good old-fashioned way:
sed 's/\(..*\) \(..*\) /\2 \1/' file.txt
Btw, always beware of the difference between BSD sed
and GNU sed
.
For example this works as expected in GNU sed
but not in BSD sed
:
sed 's/\(.\+\) \(.\+\) /\2 \1/ ' file.txt
The first two solutions in this post work in both GNU and BSD sed
.
Whenever possible, it's good to prefer syntax that will work in both,
to prevent all sorts of debugging hell.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With