Search code examples
bashsedquotesherestring

sed line number specific substitution changes every pattern on using g option and here-string


When using pipe with or without global g option gives same result:

echo -e 'hi\nhello\nhi' | sed '1s/hi/hey/g'
hey
hello
hi

works for here-string as well when not using global g option:

sed '1s/hi/hey/' <<< $(echo -e 'hi\nhello\nhi')
hey hello hi

but when using global g option and here-string replaces the pattern at every line:

sed '1s/hi/hey/g' <<< $(echo -e 'hi\nhello\nhi')
hey hello hey

Why this change in the output when using the global substitution flag and when input comes through here-string?


Solution

  • It's not got much to do with the sed script and does have a lot to do with the bash here-string notation and quotes. Use cat instead of sed and you see:

    $ echo -e 'hi\nhello\nhi' | cat
    hi
    hello
    hi
    $ cat <<< $(echo -e 'hi\nhello\nhi')
    hi hello hi
    $ cat <<< "$(echo -e 'hi\nhello\nhi')"
    hi
    hello
    hi
    $
    

    So, you can see that with the unquoted here-string, you get three words on one line. The g modifier on the sed command 1s/hi/hey/g means that both occurrences of hi on the first line of input are changed. In the absence of the g modifier, only the first occurrence on the first line is changed. The third line never gets modified because the 1 in 1s/hi/hey/ limits the changes to the first line of input.

    This also explains the 3 lines vs 1 line of output.