2

I’ve been reading about sed and found that it was evolved from grep command.

According to https://en.wikipedia.org/wiki/Sed ,

First appearing in Version 7 Unix, sed is one of the early Unix commands built for command line processing of data files. It evolved as the natural successor to the popular grep command. The original motivation was an analogue of grep (g/re/p) for substitution, hence "g/re/s".

Sed search and replace

sed 's/old/new/' Example.txt

Thus, I was wondering if grep can perform the search and replace function just like sed.

If this is possible, please let me know how to accomplish the same via grep, and not via sed.

  • 6
    grep stands for globally search a regular expression and print. So it is out of its scope to do replacements. I suggest you to use the right tool for the right job. sed or awk are better suited for this. – fedorqui Jun 26 '17 at 10:54
  • 1
    When wikipedia says about sed It evolved as the natural successor to the popular grep command. it means that grep was used to search and print a pattern, while sed can search and print or even replace a pattern. – George Vasiliou Jun 26 '17 at 12:48
  • 1
    Thanks @GeorgeVasiliou, my concerns has been addressed with your explanation. Now I understand why sed was created after that. I would like to accept this as the best answer, however this is a "comment". – Charlotte Russell Jun 26 '17 at 14:03

3 Answers3

7

grep is only meant to (and was only initially) print(ing) the lines matching a pattern. That's what grep means (based on the g/re/p ed command).

Now, some grep implementations have added a few features that encroaches a bit on the role of other commands. For instance, some have some -r/--include/--exclude to perform part of find's job.

GNU grep added a -o option that makes it perform parts of sed's job as it makes it edit the lines being matched.

pcregrep extended it with -o1, -o2... to print what was matched by capture groups. So with that implementation, even though it was not designed for that, you can actually replace:

sed 's/old/new/'

with:

pcregrep --om-separator=new  -o1 -o2 '(.*?)old(.*)'

That doesn't work properly however if the capture groups match the empty string. On an input like:

XoldY
Xold
oldY

it gives:

XnewY
X
Y

You could work around that using even nastier tricks like:

PCREGREP_COLOR= pcregrep --color=always '.*old.*' |
  pcregrep --om-separator=new -o1 -o2 '^..(.+?)old(.+)..' |
  pcregrep -o1 '.(.*).'

That is, prepend and append \e[m (coloring escape sequence) to all matching lines to be sure there is at least one character on either side of old, and strip them afterwards.

2

No, grep could not perform substitutions (in one call), that is why there was a clear need for sed (and later awk as a better language for text processing).

1

ugrep, which is compatible with GNU grep, has a --replace option, so

ugrep --replace=new old Example.txt

is the equivalent of

sed s/old/new/ Example.txt

ripgrep also has an equivalent command-line flag:

rg --replace new old Example.txt
P Varga
  • 111
  • 3