bashheredoced

ed HERELINE substitute pattern fails


Suppose you want to make an edit in all files containing a pattern. For instance, change all '2017' to '2018'. Many suggestions exist for perl, sed, and a variety of others. The ed editor is significantly simpler, if it can be made to work.

Given a file:

$ echo 2017 > fubar

Why does this not work

$ ed fubar <<< ',s/2017/2018/g\nw\n'
6
?
$ cat fubar
2017
$ 

When this does.

$ printf ',s/2017/2018/g\nw\n'|ed fubar
6
7
$ cat fubar
2018
$ 

In the end, it would be used in a loop like this

$ for i in `grep -r -l 2018`; do ed $i <<< ',s/2017/2018/g\nw\n'; done

Solution

  • printf translates the \n escape sequence to newline characters. There's no such translation in ordinary strings in the shell, and ed doesn't recognize it by itself, either, so that's not understood and you get errors.

    You can use bash $'...' strings to perform escape sequence translation.

    ed fubar <<< $',s/2017/2018/g\nw\nq\n'
    

    I've also added an explicit q command at the end. On my Mac OS system I get a ? warning if ed reads EOF.

    You could also use a here-doc:

    ed fubar <<EOF
    ,s/2017/2018/g
    w
    q
    EOF