We'll first look at actual stream editing with sed. Stream editing allows us to do really cool stuff: we could, for example, change some words in a text. We could also delete certain lines we do not care about (everything that does not contain the word ERROR, for example).
We'll begin with a simple example, searching for and replacing a word in a line:
reader@ubuntu:~/scripts/chapter_10$ echo "What a wicked sentence"
What a wicked sentence
reader@ubuntu:~/scripts/chapter_10$ echo "What a wicked sentence" | sed 's/wicked/stupid/'
What a stupid sentence
Just like that, sed transformed my positive sentence into something... less positive. The pattern sed uses (in sed terms, this is just called a script) is s/wicked/stupid/. The s stands for search-replace, and the first word of the script is substituted for the second word.
Observe what happens for multiple lines with multiple matches for the search word:
reader@ubuntu:~/scripts/chapter_10$ vim search.txt
reader@ubuntu:~/scripts/chapter_10$ cat search.txt
How much wood would a woodchuck chuck
if a woodchuck could chuck wood?
reader@ubuntu:~/scripts/chapter_10$ cat search.txt | sed 's/wood/stone/'
How much stone would a woodchuck chuck
if a stonechuck could chuck wood?
From this example, we can learn two things:
- By default, sed only replaces the first instance of each word for each line.
- sed does not match only on whole words, but also on partial words.
What if we wanted to replace all instances within each line? This is called a global search-replace, and the syntax is only very slightly different:
reader@ubuntu:~/scripts/chapter_10$ cat search.txt | sed 's/wood/stone/g'
How much stone would a stonechuck chuck
if a stonechuck could chuck stone?
By adding a g at the end of the sed script, we are now globally replacing all instances, instead of just the first instance for each line.
Another possibility is that you would only want to search-replace on the first line. You could use head -1 to only select that line before you send it through sed, but that would mean you would need to append the other lines afterwards.
We can select which lines we want to edit by placing the line numbers in front of the sed script, as follows:
reader@ubuntu:~/scripts/chapter_10$ cat search.txt | sed '1s/wood/stone/'
How much stone would a woodchuck chuck
if a woodchuck could chuck wood?
reader@ubuntu:~/scripts/chapter_10$ cat search.txt | sed '1s/wood/stone/g'
How much stone would a stonechuck chuck
if a woodchuck could chuck wood?
reader@ubuntu:~/scripts/chapter_10$ cat search.txt | sed '1,2s/wood/stone/g'
How much stone would a stonechuck chuck
if a stonechuck could chuck stone?
The first script, '1s/wood/stone/', instructs sed to replace the first instance of wood on the first line with stone. The next script, '1s/wood/stone/g', tells sed to replace all instances of wood with stone, but only on the first line. The last script, '1,2s/wood/stone/g', makes sed replace all instances of wood on all lines between (and including!) 1 and 2.