Using grep and sed to find and replace a string
You can use find
and -exec
directly into sed
rather than first locating oldstr
with grep
. It's maybe a bit less efficient, but that might not be important. This way, the sed
replacement is executed over all files listed by find
, but if oldstr
isn't there it obviously won't operate on it.
find /path -type f -exec sed -i 's/oldstr/newstr/g' {} \;
How can I grep/sed taking find/replace pairs from a file?
You can make a file with a list of sed
commands like this in a file called commands.sed
:
s|cat|cats|g
s|dog|dogs|g
s|person|people|g
and run it on some input with:
echo "House mouse cat dog person dog person" | sed -f commands.sed
and it will replace cat
with cats
, dog
with dogs
and person
with people
producing:
House mouse cats dogs people dogs people
So we want to turn your file with substitutions into a command file like that - using sed
! So, if your replacements file subs.txt
contains lines like this with the two words on each line separated by a TAB:
cat cats
dog dogs
person people
That would be:
sed -e 's/^/s|/' -e $'s/\t/|/' -e 's/$/|g/' subs.txt > commands.sed
and then you can apply it with:
sed -f commands.sed SomeFile
Rather than creating a file with the commands in, we can run a process substitution
like this to dynamically generate them, and do it all in one go with:
echo "House mouse cat dog person dog person" | sed -f <(sed -e 's/^/s|/' -e $'s/\t/|/' -e 's/$/|g/' subs.txt)
Replace string using grep and sed
sed will take multiple files as arguments, so this should work:
sed -i '/AB_/s//YZ_/g' *
(Note that -i
is non-standard)
Using grep and sed to replace one string with another
Provided you have a sed
which supports the -i
option,
sed -i 's/version: .*/version: 1.2.3/' file1 file2 file3 ...
You may want to tweak the regex wildcard; .*
matches through the end of the line, whereas [.0-9]*
matches the longest possible sequence of dots and digits. You might also want to permit for variations in surrounding whitespace ... But since this is probably among the top 10% FAQs on this site, go look for similar questions at this point.
To obtain the replacement string from file1 and apply it to file2, file3, etc, something like
new=$(sed -n 's/version: //p' file1)
# Use double quotes, not single, in order to expand $new
sed -i "s/version: [.0-9]*/version: $new/" file2 file3 ...
The first sed
invocation will only print lines on which "version: " was found and removed (replaced with an empty string). Presumably there will only be one such line in the file. Pipe the output to head -n 1
or uniq
or something, or find / create a more elaborate sed
script.
You normally use single quotes around literal strings, but since you don't want a literal $new
in the replacement, we use double quotes, which allow the shell to perform variable replacement (and a number of other substitutions we don't go into here) in the quoted string.
Find and Replace string in all files recursive using grep and sed
As @Didier said, you can change your delimiter to something other than /
:
grep -rl $oldstring /path/to/folder | xargs sed -i s@$oldstring@$newstring@g
Using sed and grep/egrep to search and replace
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"
grep or find and sed to replace string
The -i
should be an argument to sed, not to xargs. And as @potong points out, the "." characters in sed's match string must be escaped, or they'll match anything.
grep -r -l 'first.second.third.fourth' . | xargs sed -i 's/first\.second\.third\.fourth/foo.bar.fooey/g'
Related Topics
How to Increase Neo4J's Maximum File Open Limit (Ulimit) in Ubuntu
How to Get the Source Code for the Linux Utility Tail
How to Convert Yyyymmddhhmmss to a Date Readable by 'Date'
User-Data Scripts Is Not Running on My Custom Ami, But Working in Standard Amazon Linux
How to Create a Dynamic Variable and Assign Value to It
How to Modify the Source of Buildroot Packages for Package Development
Sending a Mail from a Linux Shell Script
How to Get the Difference (Only Additions) Between Two Files in Linux
Crontab Run Every 15 Minutes Except at 3Am
How to Determine If a Detached Pthread Is Alive
Why Does Printf Overwrite the Ecx Register
Start Script After Another One (Already Running) Finishes
Term Environment Variable Not Set
I Need a List of Async-Signal-Safe Functions from Glibc