Here are some examples on search and replace with Vim and Sed.
Please note that the commands starting with : are for vim and the ones starting with $ are for bash. Whatever given in () is explanation.
(1) Replace one pattern with another pattern in a file
:%s/windows/ubuntu/g
(replaces "windows" with "ubuntu" in current file)
$sed -e 's/windows/ubuntu/g' -i myfile
(-i makes an in-place replacement in myfile)
For case insensitive matching, use \c in vim and gI in sed.
:%s/windows\c/Ubuntu/g
(matches windows, Windows, winDows..... etc)
$sed -e 's/windows/Ubuntu/gI' -i myfile
(makes an in-place replacement in myfile)
(2) Replace with range
:3,5s/windows/ubuntu/g
(replaces in lines from 3 to 5)
:1,.s/windows/ubuntu/g
(from first line to current line[. represents current line])
:.,$s/windows/ubuntu/g
(from current line to last line [$ represents last line])
:.,.+15s/windows/ubuntu/g
(from current line to 15 lines below)
$sed -e '10,15 s/windows/ubuntu/g' -i myfile
(replace in lines 10 to 15)
$sed -e "10,$ s/windows/ubuntu/g' -i myfile
(replaces from 10th line to last line)
$sed -e '/begin/,/end/ s/windows/ubuntu/g' -i myfile
( replacing from pattern "begin" to pattern "end")
$sed -e '/begin/,100 s/windows/ubuntu/g' -i myfile
(from pattern "begin" to line 100)
$sed -e '/begin/,+10 s/windows/ubuntu/g' -i myfile
(from pattern "begin" to 10 lines after match)
(3) Remove lines matching or not matching a pattern
:g/windows/d
(delete all lines having pattern windows)
:10,15g/windows/d
(works with range also)
:g!/freedom/d
(delete lines not having "freedom")
$sed -e '/windows/d' -i myfile
(deletes all lines matching pattern "windows")
$sed -e '10,15 {/windows/d}' -i myfile
(specifying range restriction)
$sed -e '/freedom/!d' -i myfile
(delete all lines without "freedom")
Here onwards, examples are mostly related to regular expressions. I will be giving examples only from Vim.
(4) Pattern at the beginning or end
Use ^ for matching patterns at the beginning of line.
Use $ for patterns at the end of line.
:%s/^windows/ubuntu/g
:%s/windows$/ubuntu/g
(5) Multiple patterns
"|" ("OR" operator) can be used to match multiple patterns. Make sure to escape it with a "\"
:%s/windows xp\|windows 7/ubuntu/g
(6) Patterns with wild character
. ("dot") matches any characters except newline
:%s/a.c/pqr/g
(7) Pattern repetition
* - zero or more
+ - one or more
{n} - exactly matches n repeats
{n,m} - for repeats between n and m
{n,} - for repeats at least n
{,m} - for repeats at most m
Make sure to escape "+", "{" and "}" with "\" (for both vim and sed)
:%s/px*q/pzq/g
(matches pq, pxq, pxxq and so on)
:%s/px\+q/pzq/g
(matches pxq, pxxq, pxxxq and so on)
:%s/px\{3\}q/pzq/g
(for exact 3 x between p and q)
:%s/px\{3,\}q/pzq/g
(for at least 3 x between p and q)
(8) Lazy matching
Usual regex syntax for lazy matching is *? (where ? makes * lazy)
But in Vim, we have to use \{-\} for lazy matching (to consider as few as possible)
(I couldn't find any lazy matching option with sed :( )
Example string:
ABC ooiiooii XYZ ooiiooii XYZ
:%s/ABC.\{-\}XYZ/PQR/g
(gives PQR ooiiooii XYZ )
:%s/ABC.*XYZ/PQR/g
(gives PQR)
(9) Back reference
Expressions grouped with "( )" can be referenced with \1, \2 etc.
\1, \2 etc can be used in the replace string also.
:%s/\(ab\|xy\)_\1/pq/g
(replaces "ab_ab" and "xy_xy" with "pq", leaves "ab_xy" and "xy_ab" untouched)
:%s/pq\(.*\)rs/ab\1cd/g
("pq 123 rs" will change to "ab 123 cd")
(10) Character class
[a-z] - matches all small letter chars
[^a-z] - matches anything other than small letter
[a-zA-Z0-9] - will match all alphabets and numbers
:%s/(\([0-9]\+\))/[\1]/g
(replaces all "(number)" pattern with "[number]" pattern
Some regularly used search and replaces
(a) Remove all trailing white space
:%s/\s\+$//g
(\s- space , \+ one or more, $ - at the end)
(b) Remove ^M chars
:%s/^M//g
(Getting that ^M is bit tricky, first you need to press Ctrl-v and then press Ctrl-m)
(c) Delete blank lines
:g/^\s*$/d
(^ - beginning of line, \s* - any number of spaces, $ - end, d - delete)
(d) Remove line numbers from the beginning
:s/^[0-9]\+\s\+//g
(^ - beginning of line, [0-9]\+ - one or more numbers, \s\+ - one or more spaces)
(e) some_file.cpp(line_no) to some_file.cpp:line_no:0
%s/\(\w\+\.cpp\)(\([0-9]\+\))/\1:\2:0/g
Notes:
[1] Be always ready to go for :help regex or $man sed if you get stuck.
[2] Like all other posts, these aren't things I invented. I am just listing things I collected from net over a long time.
Please note that the commands starting with : are for vim and the ones starting with $ are for bash. Whatever given in () is explanation.
(1) Replace one pattern with another pattern in a file
:%s/windows/ubuntu/g
(replaces "windows" with "ubuntu" in current file)
$sed -e 's/windows/ubuntu/g' -i myfile
(-i makes an in-place replacement in myfile)
For case insensitive matching, use \c in vim and gI in sed.
:%s/windows\c/Ubuntu/g
(matches windows, Windows, winDows..... etc)
$sed -e 's/windows/Ubuntu/gI' -i myfile
(makes an in-place replacement in myfile)
(2) Replace with range
:3,5s/windows/ubuntu/g
(replaces in lines from 3 to 5)
:1,.s/windows/ubuntu/g
(from first line to current line[. represents current line])
:.,$s/windows/ubuntu/g
(from current line to last line [$ represents last line])
:.,.+15s/windows/ubuntu/g
(from current line to 15 lines below)
$sed -e '10,15 s/windows/ubuntu/g' -i myfile
(replace in lines 10 to 15)
$sed -e "10,$ s/windows/ubuntu/g' -i myfile
(replaces from 10th line to last line)
$sed -e '/begin/,/end/ s/windows/ubuntu/g' -i myfile
( replacing from pattern "begin" to pattern "end")
$sed -e '/begin/,100 s/windows/ubuntu/g' -i myfile
(from pattern "begin" to line 100)
$sed -e '/begin/,+10 s/windows/ubuntu/g' -i myfile
(from pattern "begin" to 10 lines after match)
(3) Remove lines matching or not matching a pattern
:g/windows/d
(delete all lines having pattern windows)
:10,15g/windows/d
(works with range also)
:g!/freedom/d
(delete lines not having "freedom")
$sed -e '/windows/d' -i myfile
(deletes all lines matching pattern "windows")
$sed -e '10,15 {/windows/d}' -i myfile
(specifying range restriction)
$sed -e '/freedom/!d' -i myfile
(delete all lines without "freedom")
Here onwards, examples are mostly related to regular expressions. I will be giving examples only from Vim.
(4) Pattern at the beginning or end
Use ^ for matching patterns at the beginning of line.
Use $ for patterns at the end of line.
:%s/^windows/ubuntu/g
:%s/windows$/ubuntu/g
(5) Multiple patterns
"|" ("OR" operator) can be used to match multiple patterns. Make sure to escape it with a "\"
:%s/windows xp\|windows 7/ubuntu/g
(6) Patterns with wild character
. ("dot") matches any characters except newline
:%s/a.c/pqr/g
(7) Pattern repetition
* - zero or more
+ - one or more
{n} - exactly matches n repeats
{n,m} - for repeats between n and m
{n,} - for repeats at least n
{,m} - for repeats at most m
Make sure to escape "+", "{" and "}" with "\" (for both vim and sed)
:%s/px*q/pzq/g
(matches pq, pxq, pxxq and so on)
:%s/px\+q/pzq/g
(matches pxq, pxxq, pxxxq and so on)
:%s/px\{3\}q/pzq/g
(for exact 3 x between p and q)
:%s/px\{3,\}q/pzq/g
(for at least 3 x between p and q)
(8) Lazy matching
Usual regex syntax for lazy matching is *? (where ? makes * lazy)
But in Vim, we have to use \{-\} for lazy matching (to consider as few as possible)
(I couldn't find any lazy matching option with sed :( )
Example string:
ABC ooiiooii XYZ ooiiooii XYZ
:%s/ABC.\{-\}XYZ/PQR/g
(gives PQR ooiiooii XYZ )
:%s/ABC.*XYZ/PQR/g
(gives PQR)
(9) Back reference
Expressions grouped with "( )" can be referenced with \1, \2 etc.
\1, \2 etc can be used in the replace string also.
:%s/\(ab\|xy\)_\1/pq/g
(replaces "ab_ab" and "xy_xy" with "pq", leaves "ab_xy" and "xy_ab" untouched)
:%s/pq\(.*\)rs/ab\1cd/g
("pq 123 rs" will change to "ab 123 cd")
(10) Character class
[a-z] - matches all small letter chars
[^a-z] - matches anything other than small letter
[a-zA-Z0-9] - will match all alphabets and numbers
:%s/(\([0-9]\+\))/[\1]/g
(replaces all "(number)" pattern with "[number]" pattern
Some regularly used search and replaces
(a) Remove all trailing white space
:%s/\s\+$//g
(\s- space , \+ one or more, $ - at the end)
(b) Remove ^M chars
:%s/^M//g
(Getting that ^M is bit tricky, first you need to press Ctrl-v and then press Ctrl-m)
(c) Delete blank lines
:g/^\s*$/d
(^ - beginning of line, \s* - any number of spaces, $ - end, d - delete)
(d) Remove line numbers from the beginning
:s/^[0-9]\+\s\+//g
(^ - beginning of line, [0-9]\+ - one or more numbers, \s\+ - one or more spaces)
(e) some_file.cpp(line_no) to some_file.cpp:line_no:0
%s/\(\w\+\.cpp\)(\([0-9]\+\))/\1:\2:0/g
Notes:
[1] Be always ready to go for :help regex or $man sed if you get stuck.
[2] Like all other posts, these aren't things I invented. I am just listing things I collected from net over a long time.
gud one vinay. i like sed for its simplicity, but never used it much because it does not keep a history of changes, where as vim does. may be i will try something now on. keep posting more.. :)
ReplyDeleteTrue. That is one dangerous thing about sed. One ugly workaround is to set up a small git repository (git init, git add ., git commit) before we run any dangerous scripts. After the script is run, we can see the differences with "git diff" and revert back with "git checkout ." if something is not proper.
DeleteLearnt some new things ( as always from you) which i am not using in vim. Thanks. keep it up. May be on Perl next time :)
ReplyDelete