【问题标题】:How to combine multiple sed and awk commands?如何组合多个 sed 和 awk 命令?
【发布时间】:2016-07-31 18:15:55
【问题描述】:

我有一个文件夹,里面有大约 200 万个文件。我需要运行以下命令:

sed -i 's/<title>/<item><title>/g;s/rel="nofollow"//g;s/<\/a> &bull;/]]><\/wp:meta_value><\/wp:postmeta><content:encoded><![CDATA[/g;s/By <a href="http:\/\/www.website.com\/authors.*itemprop="author">/<wp:postmeta><wp:meta_key><![CDATA[custom_author]]><\/wp:meta_key><wp:meta_value><![CDATA[/g' /home/testing/*

sed -i '$a]]></content:encoded><wp:status><![CDATA[draft]]></wp:status><wp:post_type><![CDATA[post]]></wp:post_type><dc:creator><![CDATA[Database]]></dc:creator></item>\' /home/testing/*

awk -i inplace 1 ORS=' ' /home/testing/*

我遇到的问题是,当我运行第一个命令时,它会循环遍历所有 200 万个文件,然后我继续执行第二个命令,依此类推。问题是我基本上总共要打开文件 600 万次。

我希望在打开每个文件时,在其上运行所有 3 个命令,然后继续执行下一个。希望这是有道理的。

【问题讨论】:

  • 你考虑过Perl吗? 正是是Perl存在的原因(IMO)。
  • 一个文件需要多长时间?也许您应该首先将文件夹划分为子文件夹/批次。更多cpu的一对一系统并想要并行处理?也许在不同的磁盘上。
  • 我想你先做一个备份。 sed -i 也会创建一个临时文件。我会将输出重定向到新文件。
  • @ElliottFrisch no 正是 this 是 AWK 存在的原因。 Perl 的存在是为了您需要做的不仅仅是操作文本。爱德华 - 编辑您的问题以包含简洁、可测试的示例输入和预期输出,不要指望我们通过阅读一堆其他脚本来尝试对您需要脚本执行的操作进行逆向工程。
  • @ElliottFrisch 同意。我用 csh,sed,awk 写了 10 年 [以任意组合]。然后,我发现了 perl。我很快意识到它可以替换 all ,我重写了所有内容以仅使用 perl。 perl 的一个优点是能够在实际运行之前使用perl -c 预先检查脚本,有点像编译器。现在,20 年后,我有 250,000 行 perl 并且从未回头。 perl [和 python] 是经过编译的成熟的编程语言,它们也可以做 shell 所做的事情或像 sed/awk 这样的模式操作程序所做的事情——还有很多很多

标签: bash shell awk command-line sed


【解决方案1】:

假设您的文件足够小,可以将单个文件作为一个整体放入内存中(并假设 GNU sed,您在没有选项参数的情况下使用 -i 意味着) :

sed -i -e ':a;$!{N;ba}; s/.../.../g; ...; $a...' -e 's/\n/ /g' /home/testing/*

上面命令中的s/.../.../g; ...;$a...代表你实际的替换和追加命令。

:a;$!{N;ba}; 将每个输入文件作为一个整体读取,然后执行所需的替换、追加和替换所有换行符,每个换行符用一个空格。[1]

这允许您在每个输入文件中使用单个 sed 命令。


[1] 您的awk 1 ORS=' ' 命令实际上使用尾随空格 而不是换行符创建输出。相比之下,应用于整个输入文件的's/\n/ /g' 只会在行之间放置一个空格,并以换行符终止整个文件(假设输入文件以一个结尾)。

【讨论】:

    【解决方案2】:

    您可以在一个 awk 命令中完成所有操作,如下所示:

    awk -i inplace -v ORS=' ' '{
        gsub(/<title>/,"<item><title>")
        gsub(/rel="nofollow"/,"")
        gsub(/<\/a> &bull;/,"]]><\/wp:meta_value><\/wp:postmeta><content:encoded><![CDATA[")
        gsub(/By <a href="http:\/\/www.website.com\/authors.*itemprop="author">/,"<wp:postmeta><wp:meta_key><![CDATA[custom_author]]><\/wp:meta_key><wp:meta_value><![CDATA[")
        print $0 "]]></content:encoded><wp:status><![CDATA[draft]]></wp:status><wp:post_type><![CDATA[post]]></wp:post_type><dc:creator><![CDATA[Database]]></dc:creator></item>"
    }' /home/testing/*
    

    但这并不意味着它一定是做你想做的最好的方式。

    以上内容依赖于我正确解释您的命令正在执行的操作,并且显然未经测试,因为您没有提供任何示例输入和预期输出。它也仍然依赖于 GNU awk 来获取 -i inplace,就像您的原始脚本一样。

    【讨论】:

      猜你喜欢
      • 2014-08-22
      • 1970-01-01
      • 2014-01-02
      • 2012-06-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-02
      • 1970-01-01
      相关资源
      最近更新 更多