adrianscheff / useful-sed
- понедельник, 15 ноября 2021 г. в 00:29:25
Useful sed scripts & patterns.
This was born in 4-5 hours of recapping sed (and many hours learning it in the first place). Since then I've spent some more hours (and counting) fixing & improving. A good way to learn something well is to also explain to others. And if I'm honest this is also for myself, later, when I forget. :)
It was Number 1 on Hacker News in hours after publication and 300+ stars on Github. Hours. Damn! All other projects combined (some of which took much more time) are in the double digit range. The low range. And this quick and dirty sed tips collection took of. I consider myself lucky to have experienced this and I'm grateful to the people who made it possible. For you I'll try and make this as good as I can.
ONE LINERS WITH SHORT EXPLANATION
sed -n '10p' myfile.txt
sed '5!/s/foo/bar/' file.txt
sed '/^hello/ s/h/H/' file.txt
sed '5,$ s/foo/bar/' file.txt
sed '/^$/d' file
sed -nE '/^foo/,/^bar/p' file.txt
sed 's_/bin/bash_/bin/sh_' file.txt
sed '\_/bin/bash_s/grep/egrep/' file.txt
sed '\_/bin/bash_s_grep_egrep_' file.txt
sed 's/[a-zA-Z]/& /g' file.txt
sed -E 's_[a-zA-Z0-9_]+.*_\1_' file.txt
sed -E 's_([a-zA-Z0-9_]*) ([a-zA-Z0-9_]*)_\2 \1_' f1
sed -E 's_([a-zA-Z0-9_]+) \1_\1_ig' f1
sed 's_foo_bar_w replaced.txt' file.txt
sed -e 's_foo_bar_' -e 's_hello_HELLO_' file.txt
#!/usr/bin/sed -f
s/a/A/
s/foo/BAR/
s/hello/HELLO/
chmod +x myscript.sed
, call with ./myscript.sed myfile.txt
sed '10p;5i\"INSERTED BEFORE LINE 5" file.txt
sed -E '/start/,/end/ s/#.*//' file.txt
sed -E '/^#/d' f1
sed '/^#/G' file.txt
sed '/start/,$ d' file.txt
sed -rn '/start/,/end/ !p' file.txt
sed '/start/q' file.txt
sed '5 r newfile.txt' file.txt
sed '/foo/a\AFTER FOO' file.txt
sed '/foo/i\BEFORE FOO' file.txt
sed '/foo/c\FOO IS CHANGED' file.txt
#!/usr/bin/sed -f
1,100 {
/foo/ !{
s_hello_HELLOOOOWORLD_
s_yes_YES_
}
}
#!/usr/bin/sed -f
/^#/ {
i\
#BEFFORE ORIGINAL COMMENt
a\
#AFTER ORIGINAL COMMENT
c\
# ORIGINAL COMMENT IS NOW THIS LINE
}
#!/usr/bin/sed -f
/^#/ {
i\#BEFORE COMMENT
r myotherfile.txt
q
}
sed 'y/abc/ABC/' file.txt
sed -E '/^#/w comments.txt' file.txt
sed -n '1~2p' file.txt
sed -i.bak 's/hello/HELLO/' file.txt
sed -E '/^#/G G' file.txt
sed '10d' file.txt
- delete line 10sed '1,10d' file.txt
- delete from line 1 to 10sed '6,$d' file.txt
- delete from line 6 to end of file ($ is end of file)sed -E '/^#/d' file.txt
- delete lines where regex matchessed -E '/DEBUG/,/END_DEBUG/d' file.txt
- delete lines between regex matches (including lines where regex matches)sed -E '/DEBUG/,30d' file.txt
- delete from line matching DEBUG to line 30sed 'a\AFTER EVERY LINE' file.txt
- append this after every line (when no address is present apply to all lines)#!/usr/bin/sed -f
1,100 {
/DEBUG/{
/DONE/d
/NOT DONE/a\TO BE DONE URGENTLY
}
}
where matches DEBUG,
delete lines containing /DONE/ and after lines containing /NOT DONE/ append.
sed '/PRODUCTION/!d' file.txt
- delete all lines not containing regex match. Note the ! in front of d.#!/usr/bin/sed -f
1,100 {
/DEBUG/ !{
/DONE/d
/NOT DONE/a\TO BE DONE URGENTLY
}
}
on lines NOT containing /DEBUG/
Perform operations
#!/usr/bin/sed -f
1,100 {
/DEBUG/ !{
/DONE/!d
}
}
on lines not containing DEBUG
delete lines NOT containing /DONE/
5d
- delete - Delete line 5.5p
- print. - print line 5 (you should call sed with -n
option when using print to only print the specified lines)5q
- quit - after line 5 quit5a\Appended
- append - after line 5. Note the backward slash in front of 'a'5c\Changed
- change - change line 5 to 'Changed'5i\Before
- insert - insert before line 5.5r newfile.txt
- read - put the contents of file 'newfile.txt' after line 55w written.txt
- write - write line 5 to 'written.txt'5s/foo/bar
- substitute - on line 5 search for foo and replace with barsed -E '/^#/G G' file.txt
- append newline to pattern space then append hold space to pattern space - insert two blank lines after every line that matches regex&
is the matched regex. sed -E '/foo/& & &/' file.txt
will triplicate the foo word\1
to \9
are the groups id's. You use a group like `sed -E 's/(foo) (bar)/\2 \1' file.txt '. In this very simple example we search for 'foo' followed by space followed by 'bar'. Then we switch these words (instead of 'foo bar' we have 'bar foo')sed 's/foo/bar/gi' file.txt
. 'g' will replace all occurrences on the line (instead of just the first as it is by default). 'i' will make the substitute case insensitive.[TO BE CONTINUED]
I love teaching others. Time is limited but donations will allow me to to help the community more. How useful was this to you? If it was I would be humbly grateful for your donation.
paypal.me/adrianscheff | patreon.com/adrianscheff | bitcoin (1NrkpsgbmmLDoDcvAvsGEMGEQhvvtw36x1) - are some ways to help me help you better.
Thank you! May you be rich as Crassus and happy as Buddha! :)
I've learned sed from the manual and various internet links. Here are some of them:
http://sed.sourceforge.net/sed1line.txt
https://www.grymoire.com/Unix/Sed.html
info sed
and man sed
NOTES
* This is not absolutely perfect and up to the highest standards of Posix and sed usage. It was kindly pointed to me by people from HN. I'll try and make this the best possible version I can and I'll listen to your feedback. I'm not a sed guru after all, just someone trying to follow the 20/80 formula (even though sometimes I go waaay overboard).
* There is no mention of the hold space (and other registers) usage. Personally I found their usage quite confusing. If this might change in the future I'll adjust this. After all, this is not "The ultimate sed reference" but "useful sed".
* There might be examples where I use -E (regexp extended option) when it is not necessarily needed. Chances are you'll want to use this in most of your operations so it might not be a bad reflex to have. Sure, you could make an alias for it in your .bashrc. Personally I try and delay usage of aliases until I feel it's absolutely necessary (as it hides some verbosity which makes the commands clearer).