2

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
jlettvin
  • 1,113
  • 7
  • 13
  • Well, as you see simple can get complex sometimes. I'm not sure if ed is present on all systems so sed is your best bet and a 'must have' in the Linux toolbox. – LMC Jan 18 '18 at 19:01
  • 1
    @LuisMuñoz, `ed` [is the standard editor](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ed.html), present on all POSIX-compliant systems. `sed` is a *stream* editor -- it isn't built to modify files in-place, and the `sed -i` option is a nonstandard extension (which major implementations implement in mutually-incompatible ways; you can't use `sed -i` the same way between BSD and GNU versions of `sed`). – Charles Duffy Jan 18 '18 at 19:11
  • BTW, `<<<` is called "here string", not "here line". – Barmar Jan 18 '18 at 19:12
  • @CharlesDuffy I think `sed -i "" ...` will work portably in both versions. The incompatibility occurs when you leave out the explicit argument after `-i`. – Barmar Jan 18 '18 at 19:14
  • @Barmar, ...that's rather uncomfortably ambiguous syntax in the GNU form, however -- it needs to make a heuristic determination of whether the argument after `-i` is an extension to append to backup files or an expression to parse (in which case further arguments are filenames). Yes, it works in practice, but I'm hesitant to trust or encourage it. – Charles Duffy Jan 18 '18 at 19:17
  • @CharlesDuffy True, if you want to use `s/foo/bar/` as your backup suffix you have to use GNU syntax and leave out the space, `-is/foo/bar/`. – Barmar Jan 18 '18 at 19:20
  • That's not nearly the valid namespace of valid expressions which `sed` can evaluate -- even the empty string is such an expression. – Charles Duffy Jan 18 '18 at 20:31

1 Answers1

4

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
Barmar
  • 741,623
  • 53
  • 500
  • 612