我尝试使用vim将分层的(xml)文件重新格式化为“每行”文件。
这是一个简化的例子。实际情况非常“大”(500k行),条目和组是任意数量。
输入文件:
<group key="abc">
<entry val="1"/>
<entry val="2"/>
<entry val="3"/>
</group>
<group key="xyz">
<entry val="1"/>
<entry val="2"/>
<entry val="3"/>
<entry val="4"/>
<entry val="5"/>
</group>
输出结果:
abc,1
abc,2
abc,3
xyz,1
xyz,2
xyz,3
xyz,4
xyz,5
请注意,我并不需要一个能够完成所有工作的神奇表达式(尽管这会很不错)。我遇到的问题是如何获取与每个条目关联的键。我相信有一个良好的习惯用法来处理这个问题。提前感谢您的帮助。
我尝试过一件事情,可能对其他人有用,具体如下:
:g/key="\(.*\)"/.;/<\/group/s/<entry /\1,<entry /g
这段代码无法正常工作的原因是匹配范围没有传递到替换部分。该表达式实际上是在寻找pat1,在那里建立一个范围,从pat2到pat3,然后用pat4替换pat3(但仅限于pat1和pat2之间的实例)。
:g/pat1/.;/pat2/s/pat3/pat4/g
解决方案
以下是最佳解决方案,通过查找条目并向后查找键来解决了问题,而不是像我之前尝试的那样构建范围和多个替换。最终有效的方法需要进行一些小修改,因此在此提供给其他人。执行重要任务的命令如下:
:g/entry/?key?,\?t.
:g/entry/norm ddpkJ
:v/entry/d
解析:
查找所有的输入行:
:g/entry/
从那里开始向后搜索,找到包含关键字的行,并将其复制到每个条目下面。
?key?,\?t.
搜索所有记录,并切换到普通模式编辑。
:g/entry/norm
交换这两行(删除关键行并将其粘贴到组行下面)。移到关键行并连接这两行。
ddpkJ
一旦所有键都映射完成,搜索没有条目的任何行并删除它们。
:v/entry/d
如果你像我一样有多个层次结构,你可以多次运行前两行代码。一旦所有内容都在单行上,就很容易将其清理成所需的最终格式。另一个主要优点是,这种解决方案可以轻松地放入脚本中,并进行重新运行。
vim -S script.vim data.file