Search code examples
regexsedfreebsd

How do I surround text beginning with ! until end of line with escape characters in sed?


I want to:

  1. prefix text beginning with a ! character in a line with ESC E (being ESC octal code \033)
  2. suffix above text with ESC F at the end of the line.

This is what I have tried:

sed $'s/\(!.*\)/\033E\1\033F/'

This is the error I get:

$ echo "test line     ! This part shall be enclosed with ESC commands" | sed $'s/\(!.*\)/\033E\1\033F/'
sh: Syntax error: Bad escape sequence

If I remove the $ sign it can be seen that the text is detected and enclosed, but sed is not being able to insert the ESC characters.

$ echo "test line     ! This part shall be enclosed with ESC commands" | sed 's/\(!.*\)/\033E\1\033F/'
test line     033E! This part shall be enclosed with ESC commands033F

I am using FreeBSD 12 sed which is expected to be a superset of the IEEE Std 1003.2 POSIC.2 specification according to the man page.


Solution

  • Apply $'..' only for the required portion:

    $ s='test line     ! This part shall be enclosed with ESC commands'
    $ echo "$s" | sed 's/\(!.*\)/'$'\033''E\1'$'\033F''/' | cat -v
    test line     ^[E! This part shall be enclosed with ESC commands^[F
    

    Not sure about other versions, but on GNU sed, you can use hexadecimal \xHH and octal \oNNN (note the o) escapes directly, so you can do:

    $ echo "$s" | sed 's/\(!.*\)/\x1BE\1\x1BF/' | cat -v
    test line     ^[E! This part shall be enclosed with ESC commands^[F
    
    $ echo "$s" | sed 's/\(!.*\)/\o033E\1\o033F/' | cat -v
    test line     ^[E! This part shall be enclosed with ESC commands^[F