使用sed和grep搜索和替换

时间:2022-01-08 09:00:37

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

我使用的是-R,后面跟着一个包含大约10个联合的正则表达式,比如:.jpg | .png | .gif等等

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.

这里的问题是,我如何在sed中做一个类似的union正则表达式,我如何告诉它将更改保存到它得到输入的文件中。

6 个解决方案

#1


175  

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

      -l:只列出匹配的文件名

    • -R: search recursively through all given directories

      -R:递归地搜索所有给定的目录

    • -Z: use \0 as record separator

      -Z:使用\0作为记录分隔符

    • "\.jpg|\.png|\.gif": match one of the strings ".jpg", ".gif" or ".png"

      “\ jpg | \ . png | \ gif”:匹配字符串“jpg”之一,”。gif或png”

    • .: start the search in the current directory

      .:在当前目录中启动搜索

  • xargs: execute a command with the stdin as argument

    xargs:以stdin作为参数执行命令

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

      -0:使用\0作为记录分隔符。这对于匹配白鹭的-Z非常重要,并且避免被输入文件名中的空格和换行所迷惑。

    • -l: use one line per command as parameter

      -l:作为参数使用一个命令行。

  • sed: the stream editor

    sed:流编辑器

    • -i: replace the input file with the output without making a backup

      -将输入文件替换为输出文件而不做备份

    • -e: use the following argument as expression

      -e:用下面的参数作为表达式

    • 's/\.jpg\|\.gif\|\.png/.bmp/g': replace all occurrences of the strings ".jpg", ".gif" or ".png" with ".bmp"

      's/\.jpg\|\.gif\|\.png/.bmp/g':替换所有出现的字符串".jpg"。gif”或“。bmp格式png”与“”

#2


11  

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

老实说,我爱sed适当的任务,这绝对是一个任务为perl,这是真正的更强大的这种俏皮话,特别是“写它回到它来自”(perl的我给您换它,选择也让你保持周围的旧版本如. bak附加,用我。贝克)。

perl -i.bak -pe 's/\.jpg|\.png|\.gif/.jpg/

rather than intricate work in sed (if even possible there) or awk...

而不是在sed(如果可能的话)或awk中进行复杂的工作。

#3


9  

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 .

find将在由…指示的当前目录上为您执行查找。

-name the name of the file in my case its pom.xml can give wild cards.

在我的示例中,将文件的名称命名为pom。xml可以给出通配符。

-exec execute

-执行

sed stream editor

sed流编辑器

-i ignore case

我忽略大小写

s is for substitute

年代是替代品

/4.6.0.../ String to be searched

/ 4.6.0……/要搜索的字符串。

/5.0.0.../ String to be replaced

/ 5.0.0……/要替换的字符串

#4


5  

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:

我无法让该页上的任何命令对我起作用:sed解决方案在它处理的所有文件的末尾添加了一个换行符,perl解决方案无法接受find的足够参数。我找到了这个完美的解决方案:

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.

这将递归到当前目录树,并在以.h或.m结尾的任何文件中使用replacement_string替换search_regex。

I have also used rpl for this purpose in the past.

我过去也曾为此目的使用rpl。

#5


0  

try something using a for loop

尝试使用for循环

 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.

不漂亮,但应该好看。

#6


0  

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.

我的用例是,我想用foo:/Drive_Letter替换为foo:/bar/baz/xyz,在我的用例中,我可以用下面的代码替换它。我在同一目录位置,那里有大量的文件。

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

更新年代| foo:/ Drive_letter:xyz | | foo:/ ba /巴兹/ g

#1


175  

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

      -l:只列出匹配的文件名

    • -R: search recursively through all given directories

      -R:递归地搜索所有给定的目录

    • -Z: use \0 as record separator

      -Z:使用\0作为记录分隔符

    • "\.jpg|\.png|\.gif": match one of the strings ".jpg", ".gif" or ".png"

      “\ jpg | \ . png | \ gif”:匹配字符串“jpg”之一,”。gif或png”

    • .: start the search in the current directory

      .:在当前目录中启动搜索

  • xargs: execute a command with the stdin as argument

    xargs:以stdin作为参数执行命令

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

      -0:使用\0作为记录分隔符。这对于匹配白鹭的-Z非常重要,并且避免被输入文件名中的空格和换行所迷惑。

    • -l: use one line per command as parameter

      -l:作为参数使用一个命令行。

  • sed: the stream editor

    sed:流编辑器

    • -i: replace the input file with the output without making a backup

      -将输入文件替换为输出文件而不做备份

    • -e: use the following argument as expression

      -e:用下面的参数作为表达式

    • 's/\.jpg\|\.gif\|\.png/.bmp/g': replace all occurrences of the strings ".jpg", ".gif" or ".png" with ".bmp"

      's/\.jpg\|\.gif\|\.png/.bmp/g':替换所有出现的字符串".jpg"。gif”或“。bmp格式png”与“”

#2


11  

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

老实说,我爱sed适当的任务,这绝对是一个任务为perl,这是真正的更强大的这种俏皮话,特别是“写它回到它来自”(perl的我给您换它,选择也让你保持周围的旧版本如. bak附加,用我。贝克)。

perl -i.bak -pe 's/\.jpg|\.png|\.gif/.jpg/

rather than intricate work in sed (if even possible there) or awk...

而不是在sed(如果可能的话)或awk中进行复杂的工作。

#3


9  

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 .

find将在由…指示的当前目录上为您执行查找。

-name the name of the file in my case its pom.xml can give wild cards.

在我的示例中,将文件的名称命名为pom。xml可以给出通配符。

-exec execute

-执行

sed stream editor

sed流编辑器

-i ignore case

我忽略大小写

s is for substitute

年代是替代品

/4.6.0.../ String to be searched

/ 4.6.0……/要搜索的字符串。

/5.0.0.../ String to be replaced

/ 5.0.0……/要替换的字符串

#4


5  

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:

我无法让该页上的任何命令对我起作用:sed解决方案在它处理的所有文件的末尾添加了一个换行符,perl解决方案无法接受find的足够参数。我找到了这个完美的解决方案:

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.

这将递归到当前目录树,并在以.h或.m结尾的任何文件中使用replacement_string替换search_regex。

I have also used rpl for this purpose in the past.

我过去也曾为此目的使用rpl。

#5


0  

try something using a for loop

尝试使用for循环

 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.

不漂亮,但应该好看。

#6


0  

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.

我的用例是,我想用foo:/Drive_Letter替换为foo:/bar/baz/xyz,在我的用例中,我可以用下面的代码替换它。我在同一目录位置,那里有大量的文件。

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

更新年代| foo:/ Drive_letter:xyz | | foo:/ ba /巴兹/ g