我有一个大约2GB的大型XML文件。为了使事情变得有趣,整个数据都在一行中。
我正在尝试在此文件中的特定标记的末尾插入换行符,以使其成为多行文件,这样我就可以将其拆分并对其执行更多操作。
root@server:~# sed -i -e 's/\<\/Dummy\>/\<\/Dummy\>\\\n/g' file_name
我尝试过sed,vi和joe没有运气。 XML中每个节点的长度不同,因此我无法根据字符数拆分文件。
我有办法通过命令行将这个大的单行文件变成多行文件吗?
答案 0 :(得分:1)
您可以做的是使用xmllint xmllint --format pathtofile.xml
将其格式化为规范xml,然后将其格式化为sed。
答案 1 :(得分:0)
我想我实际上是用gawk而不是sed来做这件事。
你没有包含输入数据,所以我会做一些。
$ printf '<a><b></b><b></b></a><a><c></c></a>' | gawk -vRS='</a>' '{print $0 RS}'
<a><b></b><b></b></a>
<a><c></c></a>
通常,awk(或gawk)会将每一行视为唯一记录,每行分为由空格分隔的字段。
如果您通过某个XML标记拆分记录,则可以依赖于print
在打印每个“输入记录”后将新行添加为默认ORS(输出记录分隔符)这一事实。
与sed解决方案不同,它会尝试将一个完整的“记录”(行)读入内存以便对其执行操作,我怀疑此解决方案只会使用足够的内存来“记住”空间来逐步执行文件记录分隔符之间。 (这解决了“大文件”问题。)
另外三件事要注意。
首先,记录分隔符不是XML原生的概念,因此任何使用sed,awk或任何本身不能解释XML 的解决方案都是黑客。使用本机支持您的数据格式的工具,您将始终获得更好的结果。
第二,因为在我的例子中,我已经指定了一个记录分隔符,即XML标记的关闭,输入数据可能有三个记录,其中第三个是null。如果在最终的“记录分隔符”后面有换行符,则第三条记录可能会在输出中的另一个RS中终止。被警告。这是事物#1的结果。
第三,这是一个 gawk 解决方案,而不是 awk 解决方案,因为其他awk实现通常不支持多个字符作为记录分隔符。
YMMV。这不是一个很好的解决方案,但它可能足以满足您的需求。
答案 2 :(得分:0)
我公然窃取了ghoti answer {/ 3}}的输入内容:
$ 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
如果您使用< >
转义\< \>
,则sed 1 认为您的意思是&#34;字边界&#34;,但在这种情况下,您的意思是文字< >
并且不应该逃避它们:
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>
结尾(示例输入有),我们可能希望从输出的末尾删除反斜杠(和换行符!): p>
$ 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会这样做,但这被标记为&#34; Linux&#34;我假设你使用的是GNU sed。
答案 3 :(得分:0)
尝试流选项:
xmllint --stream --format file_name > lintout.xml