在 Linux 中的大型单行文件 (~2GB) 文件中搜索和替换

Search and replace in a large single line file (~2GB) file in Linux

我有一个很大的 XML 文件,大小约为 2GB。为了使事情变得有趣,整个数据都在一行中。

我正在尝试在此文件中特定标记的末尾插入一个换行符,使其成为一个多行文件,这样我就可以拆分它并使用它做更多的事情。

root@server:~# sed -i -e 's/\<\/Dummy\>/\<\/Dummy\>\\n/g' file_name

我试过 sed、vi 和 joe,但没有成功。 XML中每个节点的长度不同,所以我不能根据字符数拆分文件。

有没有办法通过命令行将这个大的单行文件变成多行文件?

您可以做的是使用 xmllint xmllint --format pathtofile.xml 将其格式化为规范 xml,然后将其通过管道传输到 sed。

我想我实际上会用 gawk 而不是 sed 来做到这一点。

你没有包含输入数据,所以我会补上一些。

$ printf '<a><b></b><b></b></a><a><c></c></a>' | gawk -vRS='</a>' '{print [=10=] RS}'
<a><b></b><b></b></a>
<a><c></c></a>

通常,awk(或 gawk)会认为每一行 是一个唯一的记录,每行分成由白色分隔的字段space。

如果您改为通过某些 XML 标记拆分记录,您可以依赖 print 将在打印每个 [=40] 后附加一个换行符作为默认 ORS(输出记录分隔符) =].

与 sed 解决方案不同,sed 解决方案会尝试将整个 "record"(行)读入内存以便对其执行操作,我怀疑此解决方案只会使用足够的内存来单步执行您的文件 "remember" 记录分隔符之间的 space。 (这解决了 "large file" 问题。)

另外三点需要注意。

首先,记录分隔符不是 XML 的原生概念,因此任何使用 sed、awk 或任何不原生解释 XML 的解决方案都是 hack 。使用本身支持您的数据格式的工具,您将始终获得更好的结果。

其次,由于在我的示例中我指定了一个记录分隔符,它是 XML 标记的结尾,因此输入数据可能具有三个记录,其中第三个为空。如果您在最后一个 "record separator" 之后有一个换行符,那么第三条记录可能会在您的输出中以另一个 RS 终止。被警告。这是第一件事的结果。

第三,这是gawk方案,不是awk方案,因为其他awk实现一般不支持多字符记录分隔符。

YMMV。这不是一个很好的解决方案,但可能足以满足您的需求。

我公然从 ghoti's :

窃取我的输入
$ cat file_name
<a><b></b><b></b></a><a><c></c></a>

您的尝试有一些问题,在此处修改为较短的标签:

sed -i -e 's/\<\/a\>/\<\/a\>\\n/g' file_name
  • 在这种情况下不需要 -e:

    sed -i 's/\<\/a\>/\<\/a\>\\n/g' file_name
    
  • 为了避免转义 /,我们可以使用不同的分隔符:

    sed -i -e 's|\</a\>|\</a\>\\n|g' file_name
    
  • 如果你用\< \>转义< >,sed1认为你的意思是"word boundaries",但在这种情况下,你的意思是文字 < > 并且不应该转义它们:

    sed -i -e 's|</a>|</a>\\n|g' file_name
    

    这已经做了 一些事情:

    $ sed -i -e 's|</a>|</a>\\n|g' file_name
    <a><b></b><b></b></a>\
    <a><c></c></a>\
    [empty line here]
    

因此,如果您真的想要在每一行的末尾添加 \,我们就快搞定了。 (如果没有,您可以将 \\n 替换为 \n。)

  • 化妆品:不需要写出我们在替换中匹配的所有内容,我们可以直接使用 &:

    sed -i -e 's|</a>|&\\n|g' file_name
    
  • 最后,如果我们的文件恰好以 <a> 结尾(示例输入确实如此),我们可能希望从我们的末尾删除反斜杠(和换行符!)输出:

    $ sed -e 's|</a>|&\\n|g;s/\\n$//' file_name
    <a><b></b><b></b></a>\
    <a><c></c></a>
    

当然,关于使用非 XML 工具操纵 XML 的所有内容仍然适用:您不应该这样做,如果您这样做,预计您的解决方案很容易崩溃。


1 至少 GNU sed 可以,但这被标记为 "Linux" 我假设您使用的是 GNU sed。

尝试直播选项:

xmllint --stream --format file_name > lintout.xml