tags:

views:

5085

answers:

3

I am using egrep -R followed by a regular expression containing about 10 unions, so like: .jpg | .png | .gif etc... This works well. I would like to then 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.

Thanks for the help

+2  A: 

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...

Alex Martelli
sed uses -i, just like perl.
Stobor
+15  A: 

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 of egrep 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"
David Schmitt
rats ... beat me to it. This is a job for xargs for sure.
Zac Thompson
xargs... lost the name for a bit... and learned the -i flag for sed. Sweet
Don Johe
it all works except the | in the sed part. I don't understand why though since it makes sense... the -l part of xargs was giving me errors so I took it out, could that be related?
Ori Cohen
Why do you need -0 in xargs? How about -l?
Nathan Fellman
I hope that clears it up a bit.
David Schmitt
A: 

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.

Don Johe
xargs is definitely more appropriate here.
Nathan Fellman
and using the `|while read i` pattern would enable streaming and avoid length restrictions when egrep's results become too long
David Schmitt