Using sed and grep/egrep to search and replace
RegexSedGrepRegex Problem Overview
I am using egrep -R
followed by a regular expression containing about 10 unions, so like:
.jpg | .png | .gif
etc. This works well, now I would like to replace all strings found with .bmp
I was thinking of something like
egrep -lR "\.jpg|\.png|\.gif" . | sed "s/some_expression/.jpg/" file_it_came_form
so the issue here is how do I do a similar union regular expression in sed
and how do I tell it to save the changes to the file that it got the input from.
Regex Solutions
Solution 1 - Regex
Use this command:
egrep -lRZ "\.jpg|\.png|\.gif" . \
| xargs -0 -l sed -i -e 's/\.jpg\|\.gif\|\.png/.bmp/g'
-
egrep
: find matching lines using extended regular expressions -
-l
: only list matching filenames -
-R
: search recursively through all given directories -
-Z
: use\0
as record separator -
"\.jpg|\.png|\.gif"
: match one of the strings".jpg"
,".gif"
or".png"
-
.
: start the search in the current directory -
xargs
: execute a command with the stdin as argument -
-0
: use\0
as record separator. This is important to match the-Z
ofegrep
and to avoid being fooled by spaces and newlines in input filenames. -
-l
: use one line per command as parameter -
sed
: the stream editor -
-i
: replace the input file with the output without making a backup -
-e
: use the following argument as expression -
's/\.jpg\|\.gif\|\.png/.bmp/g'
: replace all occurrences of the strings".jpg"
,".gif"
or".png"
with".bmp"
Solution 2 - Regex
Honestly, much as I love sed for appropriate tasks, this is definitely a task for perl -- it's truly more powerful for this kind of one-liners, especially to "write it back to where it comes from" (perl's -i
switch does it for you, and optionally also lets you keep the old version around e.g. with a .bak appended, just use -i.bak
instead).
perl -i.bak -pe 's/\.jpg|\.png|\.gif/.jpg/
rather than intricate work in sed (if even possible there) or awk...
Solution 3 - Regex
Another way to do this
find . -name *.xml -exec sed -i "s/4.6.0-SNAPSHOT/5.0.0-SNAPSHOT/" {} \;
Some help regarding the above command
The find will do the find for you on the current directory indicated by .
-name
the name of the file in my case its pom.xml can give wild cards.
-exec
execute
sed
stream editor
-i
ignore case
s
is for substitute
/4.6.0.../
String to be searched
/5.0.0.../
String to be replaced
Solution 4 - Regex
I couldn't get any of the commands on this page to work for me: the sed solution added a newline to the end of all the files it processed, and the perl solution was unable to accept enough arguments from find. I found this solution which works perfectly:
find . -type f -name '*.[hm]' -print0
| xargs -0 perl -pi -e 's/search_regex/replacement_string/g'
This will recurse down the current directory tree and replace search_regex
with replacement_string
in any files ending in .h
or .m
.
I have also used rpl for this purpose in the past.
Solution 5 - Regex
try something using a for loop
for i in `egrep -lR "YOURSEARCH" .` ; do echo $i; sed 's/f/k/' <$i >/tmp/`basename $i`; mv /tmp/`basename $i` $i; done
not pretty, but should do.
Solution 6 - Regex
My use case was I wanted to replace
foo:/Drive_Letter
with foo:/bar/baz/xyz
In my case I was able to do it with the following code.
I was in the same directory location where there were bulk of files.
find . -name "*.library" -print0 | xargs -0 sed -i '' -e 's/foo:\/Drive_Letter:/foo:\/bar\/baz\/xyz/g'
hope that helped.
UPDATE s|foo:/Drive_letter:|foo:/ba/baz/xyz|g