Search code examples
regexsedgnu-sed

Replace one capture group with another with GNU sed (macOS) 4.4


I've looked around some other peripheral questions and haven't been able to find a solution to my problem, so I'm sorry if this is a duplicate to something I missed.

Basically, I have the following GNU sed command:

sed -E -imr 's/^(\w)+/(\w)+$/g' file

which is supposed to replace the first word of a line with the last word of the line.

The first regex ^(\w)+ works great and matches the first word of each line. The problem is that the command replaces that first word with the literal string (w)+$

I've tried to escape the backslash, the parentheses, the operators, but I've had no luck in making the regex work in the output part of the command.

Can one use a regex capture group to replace a different regex capture group? What needs to be escaped, or what alternative syntax needs to be used?

NOTE

I'm using GNU sed on macOS from brew installed coreutils, so the answers to this question might not work across other versions of sed like native BSD on macOS.


Solution

  • The replacement doesn't contain a regex, it contains a string which could reference capture groups defined in the regex. To replace the first word by the last one, you need to capture the last word and the rest of the line:

    sed -r 's/^\w+(.*\b)(\w+)$/\2\1/'  
                |    |    |
             Matches |    |
             the 1st |    Matches the last word
             word    |
                    Matches everything in the middle
                    up to a "word boundary"
    

    Note that -r, \w, and \b might not work in all sed versions, but they should work in recent GNU sed.