Reshape text

INPUT · Slides

Swap one piece of text for another (`sed`)

01 / 07

What tr could not do

tr swapped characters one at a time, which is why it could not do this.

change the word error into ERROR

Hand tr the words error and ERROR and it makes a character by character pairing: e to E, r to R, r to R, o to O, r to R. It never treats them as words.

The tool that swaps text for text is sed, short for stream editor.

02 / 07

s/from/to/ is the basic shape

What you use most in sed is s (substitute).

sed 's/error/ERROR/' log.txt

Read it like this.

s / what to look for / what to put instead /

The / is the separator and you need three of them. The single quotes stop the shell misreading the / and *.

Unlike tr, you can write a file name. < and pipes work too, but writing it directly is easier.

~ $ sed 's/error/ERROR/' log.txtERROR: disk fullok: startedERROR: no route

03 / 07

Without a g it only does one

Here is the part that catches people. By default sed swaps only the first one on each line.

~ $ sed 's/one/1/' repeats.txt1 one onetwo two

There are three one and only the first changed.

To change them all, put a g (global) on the end.

~ $ sed 's/one/1/g' repeats.txt1 1 1two two

Forgetting the g and getting "only one changed" is a mistake everybody makes once. There are also times you want only the first one changed, so the default is not a waste.

04 / 07

The separator does not have to be /

When you want to swap a path (a file location), the / everywhere makes it unreadable.

sed 's/\/home\/guest/\/tmp/' path.txt    # unreadable

In fact the separator can be any character you like. Whatever comes after the s becomes the separator.

sed 's|/home/guest|/tmp|' path.txt      # readable

|, # and , are common choices.

The knack is to pick a character that does not appear in the text. Without this you end up writing unreadable commands full of backslashes.

05 / 07

Choose lines, delete lines

sed does more than swapping.

-n and p to choose (-n is "do not put anything out by yourself", p is print)

sed -n '2p' abcde.txt      # line 2 onlysed -n '2,4p' abcde.txt    # lines 2 to 4sed -n '$p' abcde.txt      # the last line

d to delete

sed '2d' abcde.txt         # remove line 2sed '/error/d' log.txt     # remove lines containing error

sed '/error/d' is the same as grep -v error. Several tools doing the same thing is nothing new by now.

06 / 07

-i rewrites the file (dangerous)

Everything so far only put the result on the screen; the original file never changed.

Add -i (in-place) and it rewrites the file itself.

sed -i 's/error/ERROR/' log.txt

Handy, but there is no going back. Nothing will undo it.

There are two safe ways to use it.

1. Type it without -i first, check the result, then add the -i
2. Write -i.bak (it keeps a copy as log.txt.bak)

sed -i.bak 's/error/ERROR/' log.txt

Check, then rewrite. The same thing was said about >. Before anything you cannot take back, look at it once.

07 / 07

Now have a go

Five files.

  • log.txt — three lines: error:, ok:, error:
  • grades.csvtanaka,80 and suzuki,95
  • repeats.txtone one one and two two
  • abcde.txt — five lines, a to e
  • path.txt — two lines such as /home/guest/a.txt

Do not forget the single quotes. Without them the shell may misread the / and *.

sed is a deep tool, deep enough for a whole book of its own. But what you use for daily work is mostly s/from/to/g. Get that into your hands first.