Regex 范围中的多行vim正则表达式替换

Regex 范围中的多行vim正则表达式替换,regex,vim,multiline,Regex,Vim,Multiline,我正在尝试使用vim将分层(xml)文件重新格式化为“每行”文件。 这里是一个简化的例子。实际情况是“大”(500k线),条目和组是任意计数 输入文件: <group key="abc"> <entry val="1"/> <entry val="2"/> <entry val="3"/> </group> <group key="xyz"> <entry val="1"/> <entr

我正在尝试使用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>
请注意,我不需要一个单独的魔法表达式来完成所有这一切(尽管那太棒了)。我正在努力解决的问题是获取与每个条目相关联的密钥。我相信有一个很好的习惯用法来处理这个问题。提前谢谢

我尝试过的一件事可能对其他人有用,如下所示:

:g/key="\(.*\)"/.;/<\/group/s/<entry /\1,<entry /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

好吧,这不是一句神奇的台词,但可能有用:

ggqq/groupf"lyi"<c-v>n0I<c-r>"<esc>ddnddq
100@q
:%s/\s*<entry val="/,/g
:%s/"\/>//g
ggqq/groupf“lyi”n0I“ddnddq
100@q
:%s/\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
gg=>转到顶部
qq=>录制一个名为q的宏
/组=>搜索“组”
f“l=>转到键
yi“=>复制密钥
c-v=>垂直视觉模式
n0=>转到“组”的末尾,将光标放在开头
I“=>在开头粘贴
dd=>删除行
ndd=>删除结束行
q=>停止宏
100@q=>播放宏100次,需要时使用
现在,您应该有如下内容:

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"/>
abc
abc
abc
xyz
xyz
xyz
xyz
xyz
然后只需清洁您不需要的东西:

:%s/\s*<entry val="/,/g
:%s/"\/>//g
:%s/\s*//g
以下方法可行

:g/entry/?<group?,?<group?t.
:%norm J
:g/<\//d
:%norm df"f"df"i,<C-v><Esc>f"d$
连接所有线路

:%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>
:%norm J
移除结束标记

: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"/>

:g/我发现一个几乎让我开始学习的好技巧是表达式::g/把你试过的东西放在问题中。(格式化会让它看起来更好)谢谢@FDinoff。完成。(第一篇帖子)你能把“帕特”和“帕特”分解一下吗。范围表达式?与依赖于文件完全平衡的:%norm J不同,我做了:g/entry/norm kJ,它查找所有条目行,移动到粘贴组的上面一行并连接它们。这支持多个级别。最佳答案,因为它巧妙地反转了我正在进行的搜索替换。这也适用于存在其他层次结构的情况。一旦我在一行上得到了我需要的所有数据,其他所有的数据都被清除了。然后它就成了%s/垃圾/,/直到完成为止。谢谢欢迎光临。以防你还需要?帕特?范围表达式解释,它只是从当前选中的行(在我们的例子中是一个入口行)向后搜索一个“组”行,并将范围设置为1行(我认为可以缩短,但还没有尝试)。“t”复制当前行下方的范围(我们的一行)。谢谢。我不知道:t命令。同义词:复制。该范围可以缩短为:?pat?,\?哪里\?搜索以前使用的搜索模式匹配的前一行。感谢您的解决方案。qq宏习语是我很久没用过的。这适用于中小型文件,因为它是交互式的。我不得不在vim之外做大量的行计数工作,以计算对于一个非常大的文件,要重放宏多少次。
: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"/>
:%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