gpt4 book ai didi

regex - 范围内的多行 vim 正则表达式替换

转载 作者:行者123 更新时间:2023-12-02 01:44:04 25 4
gpt4 key购买 nike

我正在尝试使用 vim 将分层 (xml) 文件重新格式化为“每行”文件。

这是一个简化的例子。实际情况是“大”(50 万行),条目和组是任意计数。

输入文件:

<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

请注意,我不需要一个神奇的表达式来完成所有这些(尽管那会很膨胀)。我正在努力解决的部分是获取与每个条目关联的 key 。我确定有一个很好的习惯用法来处理这个问题。提前致谢。

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

: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 的行并将其复制到每个条目下方。

?key?,\?t.

再次搜索所有入口行,切换到普通模式编辑

:g/entry/norm

交换两行(删除关键行并将其粘贴到组行下方)。向上移动到关键线并加入两条线。

ddpkJ

一旦所有的键都被映射,搜索任何没有条目的行并删除它们。

:v/entry/d

如果您像我一样有多个层次结构,则可以多次运行前两行。一旦所有内容都在一行中,就可以非常简单地将其清理成所需的任何最终格式。另一个主要好处是这个解决方案可以很容易地放在脚本中并重新运行

vim -S script.vim data.file

最佳答案

以下是可行的

: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

关于regex - 范围内的多行 vim 正则表达式替换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26747094/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com