【问题标题】:Using sed and grep/egrep to search and replace使用 sed 和 grep/egrep 进行搜索和替换
【发布时间】:2010-11-13 06:50:36
【问题描述】:

我使用 egrep -R 后跟一个包含大约 10 个联合的正则表达式,例如: .jpg | .png | .gif 等。这很好用,现在我想用 .bmp 替换所有找到的字符串

我在想类似的东西

egrep -lR "\.jpg|\.png|\.gif" . | sed "s/some_expression/.jpg/" file_it_came_form

所以这里的问题是如何在sed 中执行类似的联合正则表达式,以及如何告诉它将更改保存到它从中获取输入的文件中。

【问题讨论】:

  • 我在寻找跨目录层次结构中的多个文件进行搜索和替换的方法时发现了这个问题。对于我这种情况的其他人,请尝试rpl
  • 谢谢你 rpl 工作,而且真的很容易记住.. 只是 rpl old_string new_string target_files。

标签: regex sed grep


【解决方案1】:

使用这个命令:

egrep -lRZ "\.jpg|\.png|\.gif" . \
    | xargs -0 -l sed -i -e 's/\.jpg\|\.gif\|\.png/.bmp/g'
  • egrep:使用扩展正则表达式查找匹配行

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

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

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

    • "\.jpg|\.png|\.gif":匹配字符串".jpg"".gif"".png"之一

    • .:在当前目录开始搜索

  • xargs:以标准输入为参数执行命令

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

    • -l:每条命令使用一行作为参数

  • sedstreameditor

    • -i: 用输出替换输入文件而不做备份

    • -e:使用以下参数作为表达式

    • 's/\.jpg\|\.gif\|\.png/.bmp/g':用".bmp"替换所有出现的字符串".jpg"".gif"".png"

【讨论】:

  • 除了 |在 sed 部分。我不明白为什么,因为它是有道理的...... xargs 的 -l 部分给了我错误,所以我把它拿出来了,这可能是相关的吗?
  • 我发现这个命令在它处理的所有文件的末尾添加了一个换行符。
  • @titanumdecoy:我无法重现这种行为。您使用的是什么版本的 sed 以及您在哪个操作系统上?
  • @DavidSchmitt:您可能希望将sed -r 用于扩展正则表达式。此时,模式将匹配 egrep 中使用的模式,您可能希望将其放入变量中以供重用。
  • 在 OSX 上,您必须向 sed -i 提供一个空文件,例如:sed -i '' 才能正确更改内容。
【解决方案2】:

我的用例是我想替换 foo:/Drive_Letterfoo:/bar/baz/xyz 就我而言,我可以使用以下代码来做到这一点。 我位于有大量文件的同一目录位置。

find . -name "*.library" -print0 | xargs -0 sed -i '' -e 's/foo:\/Drive_Letter:/foo:\/bar\/baz\/xyz/g'

希望有所帮助。

更新 s|foo:/Drive_letter:|foo:/ba/baz/xyz|g

【讨论】:

  • 您可以为 sed 命令使用其他分隔符,这样做可以使路径名更好:sed 's|foo:/Drive_letter:|foo:/ba/baz/xyz|g'
【解决方案3】:

另一种方法

find . -name *.xml -exec sed -i "s/4.6.0-SNAPSHOT/5.0.0-SNAPSHOT/" {} \;

关于上述命令的一些帮助

find 将在. 指示的当前目录中为您进行查找

-name 文件名,在我的例子中,它的 pom.xml 可以提供通配符。

-exec执行

sed流编辑器

-i忽略大小写

s 是替代品

/4.6.0.../要搜索的字符串

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

【讨论】:

  • 也许没有那么强大 - 但这对我来说比接受的答案更容易理解
  • @icc97 - 我同意它更容易理解,但我想不出任何原因会导致它不那么强大。
【解决方案4】:

我无法让此页面上的任何命令为我工作:sed solution 在它处理的所有文件的末尾添加了一个换行符,perl solution 无法从 find 接受足够的参数.我发现这个解决方案非常有效:

find . -type f -name '*.[hm]' -print0 
    | xargs -0 perl -pi -e 's/search_regex/replacement_string/g'

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

我过去也为此使用过rpl

【讨论】:

    【解决方案5】:

    使用 for 循环尝试一些东西

     for i in `egrep -lR "YOURSEARCH" .` ; do echo  $i; sed 's/f/k/' <$i >/tmp/`basename $i`; mv /tmp/`basename $i` $i; done
    

    不漂亮,但应该可以。

    【讨论】:

    • xargs 在这里肯定更合适。
    • 并且使用|while read i 模式可以在 egrep 的结果变得太长时启用流式传输并避免长度限制
    【解决方案6】:

    老实说,尽管我很喜欢 sed 执行适当的任务,但这绝对是 perl 的任务——对于这种单行代码来说,它确实更强大,尤其是“将它写回它的来源”(perl 的 @ 987654321@ 开关为您完成,并且还可以选择让您保留旧版本,例如附加 .bak,只需使用 -i.bak 代替)。

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

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

    【讨论】:

    • sed 使用 -i,就像 perl 一样。
    • @Stobor - 我发誓我遇到了问题,当我提供正则表达式替换字符串时,perl 操作完全符合我的要求,这与 sed 不同,即使我将正则表达式选项提供给 sed。 . 我想我要么忘记了一些要 sed 的标志,要么它有限制。
    猜你喜欢
    • 2011-07-29
    • 2019-06-27
    • 1970-01-01
    • 1970-01-01
    • 2014-09-13
    • 2018-08-21
    • 2015-01-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多