我正在尝试使用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,然后用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
答案 0 :(得分:1)
嗯,这不是一个神奇的行,但可能有效:
ggqq/groupf"lyi"<c-v>n0I<c-r>"<esc>ddnddq
100@q
:%s/\s*<entry val="/,/g
:%s/"\/>//g
一步一步:
gg => Go to the top
qq => Record a macro called q
/group => Search for "group"
f"l => Go to the key
yi" => Copy the key
c-v => Vertical visual mode
n0 => Go to the end of the "group", place the cursor at the beginning
I<c-r>"<esc> => Paste at the beginning
dd => Delete <group> line
ndd => Delete end </group> line
q => Stop macro
100@q => Play macro 100 times, use whatever you need
现在你应该有:
abc <entry val="1"/>
abc <entry val="2"/>
abc <entry val="3"/>
xyz <entry val="1"/>
xyz <entry val="2"/>
xyz <entry val="3"/>
xyz <entry val="4"/>
xyz <entry val="5"/>
然后只需清理你不需要的东西:
:%s/\s*<entry val="/,/g
:%s/"\/>//g
答案 1 :(得分:1)
以下工作
:g/entry/?<group?,?<group?t.
:%norm J
:g/<\//d
:%norm df"f"df"i,<C-v><Esc>f"d$
<强>击穿强>
对于包含entry
的每一行,向后搜索<group
并复制到条目下方的行
:g/entry/?<group?,?<group?t.
<group key="abc">
<entry val="1"/>
<group key="abc">
<entry val="2"/>
<group key="abc">
<entry val="3"/>
<group key="abc">
</group>
<group key="xyz">
<entry val="1"/>
<group key="xyz">
<entry val="2"/>
<group key="xyz">
<entry val="3"/>
<group key="xyz">
<entry val="4"/>
<group key="xyz">
<entry val="5"/>
<group key="xyz">
</group>
加入所有行
:%norm J
<group key="abc"> <entry val="1"/>
<group key="abc"> <entry val="2"/>
<group key="abc"> <entry val="3"/>
<group key="abc"> </group>
<group key="xyz"> <entry val="1"/>
<group key="xyz"> <entry val="2"/>
<group key="xyz"> <entry val="3"/>
<group key="xyz"> <entry val="4"/>
<group key="xyz"> <entry val="5"/>
<group key="xyz"> </group>
删除结束标记
:g/<\//d
<group key="abc"> <entry val="1"/>
<group key="abc"> <entry val="2"/>
<group key="abc"> <entry val="3"/>
<group key="xyz"> <entry val="1"/>
<group key="xyz"> <entry val="2"/>
<group key="xyz"> <entry val="3"/>
<group key="xyz"> <entry val="4"/>
<group key="xyz"> <entry val="5"/>
通过搜索和删除引号来修复剩余的文本。 请注意,<C-v><Esc>
是在命令中添加转义的关键序列。
:%norm df"f"df"i,<C-v><Esc>f"d$
abc,1
abc,2
abc,3
xyz,1
xyz,2
xyz,3
xyz,4
xyz,5