【问题标题】:How to sed search and replace without changing ownership如何在不更改所有权的情况下进行 sed 搜索和替换
【发布时间】:2011-02-06 07:11:00
【问题描述】:

我找到了这个命令行搜索和替换示例:

find . -type f -print0 | xargs -0 sed -i 's/find/replace/g'

它运行良好,只是它更改了它搜索的每个文件的日期和文件所有权,即使是那些不包含搜索文本的文件。

这个任务有什么更好的解决方案?

【问题讨论】:

    标签: unix sed replace


    【解决方案1】:

    使用-c 选项(如果您在Linux 上)应该会导致sed 保留所有权。当您使用该命令时,它实际上是在重写每个文件,即使它没有对不包含find 的文件进行更改。

    【讨论】:

    • 啊刚刚注意到了。谢谢。
    • sed 的哪些版本有-c?我的 GNU sed 4.2.1 没有。
    • 我在此处的手册页中工作:linux.die.net/man/1/sed -- 我使用的 CentOS 4 安装上的 sed 手册页显示 -c 作为选项,sed --version 报告 GNU sed version 4.1.2;同样适用于 CentOS 5 安装,其中sed --version 报告GNU sed version 4.1.5; MacOSX 没有 -c 选项,这就是我指定 Linux 的原因。
    • 对于 googlers:看来-c 确实不在 GNU sed 中,它是 RedHat 添加的补丁(最近添加在这里:bugzilla.redhat.com/show_bug.cgi?id=566455,更新日志在这里:rpmfind.net/linux/RPM/centos/7.2.1511/x86_64/Packages/…)。其他发行版可能也加入了它,但我在 Arch 中没有它,它不在 GNU 的手册页中:gnu.org/software/sed/manual/sed.txt
    【解决方案2】:

    解决此问题的最简单方法是仅在文件包含文本时才对文件执行 sed,首先使用 grep:

    find . -type f | while read file; do
        grep -q find $file && sed -i 's/find/replace/g' $file
    done
    

    这确实需要读取每个文件两次(在最坏的情况下),所以它可能会慢一点。不过,希望您的操作系统应该将文件保存在其磁盘缓存中,因此您不应该看到太多的减速,因为这个过程肯定是 I/O 密集型的,而不是 CPU 密集型的。

    【讨论】:

    • 根据 Isaac 的回答,我必须在您的解决方案中添加 -c 以防止所有权发生变化,对吧?
    • 不必使用grep+sed。 sed '/find/s/find/replace/g'
    • grep 是为了避免将 sed 应用于不需要更改的文件,从而避免更改其修改时间。
    【解决方案3】:

    一些发行版的sed(即RedHat 和家族)添加了一个-c 选项来完成此操作,在这种情况下请参阅@Isaac 的答案。

    但是对于那些使用未打补丁的 GNU sed 的人,我发现的最简单的方法是简单地替换为 perl,它会在可用时重写类似于 sed -c 的文件。以下命令基本等价:

    sed -ci 's/find/replace/'
    perl -pi -e 's/find/replace/'
    

    不要太激动,做perl -pie;与sed -ie 一样,它不会将其解释为另一个选项,而是将e 作为-i 的参数,并将其用作备份原始文件的后缀。有关详细信息,请参阅perldoc perlrun

    对于更复杂的事情,Perl 的正则表达式解析与 sed(更好,imo)略有不同:一般来说,使用较少的反斜杠。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-03-01
      • 1970-01-01
      • 2019-06-27
      • 1970-01-01
      • 2014-09-13
      • 2010-11-13
      • 2013-01-29
      • 2011-07-10
      相关资源
      最近更新 更多