Skip to content

sed

sed is the stream editor.

Tips

OSX Pitfalls

Beware that BSD sed -i requires a mandatory flag for the backup file. You can use -i '' to have no backup file.

Also, OS X sed doesn't support case insensitivity! WTF?! We have to use perl -pe 's/foo/bar/i' foo.txt or homebrew's gsed.

Only print a specific line

This will print only the second line of the file

sed -n ' 2{p;q;}' foo.txt

Only print if match

This will perform a replacement and print the result. Use -i (with caution!) to edit the file at the same time.

sed -n 's/\(127.[0-9]\{1,3\}.[0-9]\{1,3\}.[0-9]\{1,3\}\)/\1 localhost localhost4/p' /etc/hosts

Add a new line with content after a match

Since sed can't insert things like \n, this has to take place on multiple lines, so it's a bit funky looking but still functional.

sed -i "" -e '/respawn/a\
respawn limit 10 5' app_worker_*.conf
sed -n '/ROUTING TABLE/,$p' /etc/openvpn/openvpn-status.log

The syntax in both of these is <sed_address_one>,<sed_address_two> <action>

$ k describe pod -n moms-iot-oven cookie-baker-2022-proxy |
sed -ne '/^Events/,$ p;'
Events:
  Type    Reason   Age                       From     Message
  ----    ------   ----                      ----     -------
  Normal  Pulling  56m (x1281 over 4d13h)    kubelet  Pulling image "ubuntu:2004"
  Normal  BackOff  118s (x29062 over 4d13h)  kubelet  Back-off pulling image "ubuntu:2004"

That says "Do not print each line by default (-n). Start at the sed address which is a 'context address' regex /^Events/, and end at the special sed address $ which means the last line of input, and print those lines. (All of this info is in the man page.)

Or if you don't want to include the match:

sed -e '1,/^Events/ d'

This says "Start at line one and delete every line up to and including the match ^Events."

This will print the contents of the log file between ROUTING TABLE and GLOBAL STATS inclusive.

sed -n '/^ROUTING TABLE/,/^GLOBAL STATS/p;/^GLOBAL STATS/q' /etc/openvpn/openvpn-status.log

Or as a bash function

show-contents-between() { sed -n "/$1/,/$2/p;/$2/q"; }

Uncomment a line that matches a regex

This removes the comment and adds wheel to the sudoers list

/bin/sed -i '/^#\s\+%wheel\s\+ALL=(ALL)\s\+ALL$/s/^#\s*//' /etc/sudoers

Delete lines containing a string

sed -i -e '/root/d' asdf.txt

Delete lines not containing a string

sed -i '/foo/!d' wy.txt

Or not containing a MAC address:

sed -i '' -E '/[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}/!d' *

Do a replacement on all files in a dir

sed -i "s/foo/bar/g" /etc/apache2/sites-available/*

Switch all github urls from http to ssh

sed '/url = /s%https?://github.com/\([^/]*/[^/]*\)%git@github.com:\1%' ~/code/*/.git/config

Word boundaries

Normally, word boundaries look like this:

/\bMyWord\b/

or

/\<myword\>/

But in OS X, you have to do them like this:

/[[:<:]]MyWord[[:>:]]/

Which is just ridiculous, so use homebrew's gsed if you can.

Add a bell to tail

tail -n 0 -f /var/log/messages | sed 's/$/\a'

See Also