【问题标题】:Replacing huge blocks with sed用 sed 替换大块
【发布时间】:2010-11-24 14:13:42
【问题描述】:

我有 2 个在其他地方生成的文件。第一个是“搜索什么”,第二个是替换。这两个文件都很大,每个大约 2-3mb。

我需要编写一个 bash 脚本,它需要一个更大的文件(大约 200-300mb)并将所有出现的 file1 内容替换为 file2 内容。

问题是,file1 和 file2 可以包含任何可能的字符,包括正则表达式特殊符号。

如何使用 sed 解决这个问题?

提前致谢。

【问题讨论】:

  • 是否有特定原因必须为此使用 sed?
  • “要搜索的内容”文件是一个长模式还是一个模式列表与替换列表逐行对应(而不是一个长替换文本)?
  • Artelius:嗯,我无法将整个文件加载到内存中,如果有任何其他流替换工具,我会很高兴知道的。丹尼斯:这是 1 个大模式

标签: bash scripting sed


【解决方案1】:

也许看看 chgrep:

http://www.bmk-it.com/projects/chgrep/

干杯,

格雷克斯

【讨论】:

    【解决方案2】:

    由于您实际上不需要正则表达式,只需直接字符串匹配,sed 就大材小用了。您真正需要的是一个固定字符串(甚至可能是二进制)流编辑器。不幸的是,我不知道......我不想建议可能重新发明一个轮子,但你可以用 C 相当快地写一些东西来做你想做的事。粗略的大纲:

    • 将搜索文件读入内存
    • 创建一个与搜索文件大小相同的缓冲区
    • 从标准输入(或输入文件)读取到缓冲区。
      • 对于每个字符,如果它与搜索文件中的并行字符不匹配,则移动缓冲区。要找出要移动多少,请阅读直到找到与 input-file 的第一个字符匹配,然后检查其余部分是否匹配,重复直到找到与 input-file 的部分匹配(或得到到缓冲区的末尾)。移位时,将所有不匹配的字符打印到标准输出(或输出文件)
      • 如果缓冲区已满,即完全匹配输入文件,则将替换文件打印到标准输出(或输出文件)。根据内存与速度,您可以将替换文件保存在内存中或每次从磁盘中读取。

    您还可以尝试自动转义输入文件中的所有正则表达式字符。这可以通过一个非常丑陋的sed 替换列表来完成,比如

    sed -e 's/\\/\\\\/g' -e 's@/@\/@' -e 's/\[/\\[/g' ...
    

    (确保你先做\!)

    【讨论】:

      【解决方案3】:

      我不知道 sed,但在 Perl 中你可以做到(在我的脑海中,未经测试):

      perl -0777 -pe 'BEGIN{local $/ = undef; open FROM, "<", shift @ARGV; $from = <FROM>; open TO, "<" shift @ARGV; $to = <TO>} s/\Q$from\E/$to/sog' file1 file2 bigger-file > new-bigger-file
      

      如果你有兴趣尝试 Perl,我明天可以为你测试一下。

      但它会将整个较大的文件吸入内存,因为它会忽略换行符,因此您的搜索文本可以跨越多行。这意味着它会占用大量内存!

      此答案假定搜索文件是一个多行的长搜索字符串,必须完整匹配,而不是多个单独的搜索字符串,其中任何一个都可以匹配。

      【讨论】:

      • 是的,这就是为什么我认为 sed 是最佳解决方案的原因,因为它不需要将所有内容加载到内存中,而是在流上运行。
      • Perl 可以像 sed 一样逐行操作,但如果您一次替换 2-3mb 的块(大概超过 1 行),这将没有用。
      猜你喜欢
      • 2020-02-02
      • 2012-10-14
      • 2010-10-27
      • 1970-01-01
      • 1970-01-01
      • 2014-06-14
      • 1970-01-01
      • 1970-01-01
      • 2020-01-19
      相关资源
      最近更新 更多