提问人:Léo Léopold Hertz 준영 提问时间:4/10/2009 最后编辑:EddieLéo Léopold Hertz 준영 更新时间:4/11/2009 访问量:617
如何在 VIM 中从 A 到 B 重复匹配?
How can I repeatedly match from A until B in VIM?
问:
我需要获取 和 之间的所有文本,其中出现单词。如何在 VIM 中做到这一点?<Annotation>
</Annotation>
MATCH
<Annotation about="MATCH UNTIL </Annotation> " timestamp="0x000463e92263dd4a" href=" 5raS5maS90ZWh0YXZha29rb2VsbWEvbGFza2FyaS8QyrqPk5L9mAI">
<Label name="las" />
<Label name="_cse_6sbbohxmd_c" />
<AdditionalData attribute="original_url" value="MATCH UNTIL </Annotation> " />
</Annotation>
<Annotation about="NO MATCH" href=" Cjl3aWtpLmhlbHNpbmtpLmZpL2Rpc3BsYXkvbWF0aHN0YXRLdXJzc2l0L0thaWtraStrdXJzc2l0LyoQh_HGoJH9mAI">
<Label name="_cse_6sbbohxmd_c" />
<Label name="courses" />
<Label name="kurssit" />
<AdditionalData attribute="original_url" value="NO MATCH" />
</Annotation>
<Annotation about="MATCH UNTIL </ANNOTATION> " score="1" timestamp="0x000463e90f8eed5c" href="CiZtYXRoc3RhdC5oZWx zaW5raS5maS90ZWh0YXZha29rb2VsbWEvKhDc2rv8kP2YAg">
<Label name="_cse_6sbbohxmd_c" />
<Label name="exercises_without_solutions" />
<Label name="tehtäväkokoelma" />
<AdditionalData attribute="original_url" value="MATCH UNTIL </ANNOTATION>" />
</Annotation>
答:
它必须在 vim 中完成吗?你能作弊吗,打开第二个窗口,在其中你通过管道将一些东西输送到或多或少中,告诉你在 vim 中要转到哪个行号?
--编辑--
我从未在 vi[m] 中进行过多行匹配/搜索。但是,要在另一个窗口中作弊:
perl -n -e 'if ( /<tag/ .. /<\/tag/)' -e '{ print "$.:$_"; }' file.xml | less
将显示“标签”(或其他较长匹配的名称)的元素/块,以及行号,以 less 为单位,然后您可以在每个块中搜索其他文本。
够近吗?
--编辑--
在“less”中,键入
/MATCH
以搜索 MATCH 的出现次数。左边距将是该实例(在目标元素/标签内)所在的行号。
在 vi[m] 中,键入
:n
其中“n”是所需的行号。
当然,如果你真正想做的是某种搜索/拉扯/替换,那就更复杂了。在这一点上,awk / perl / ruby(或类似的东西,符合你的口味......还是 xsl?确实是您应该用于转换的工具。
评论
首先,免责声明:任何使用正则表达式对 XML 进行切片和切块的尝试都是脆弱的;一个真正的XML解析器会做得更好。
模式:
\(<Annotation\(\s*\w\+="[^"]\{-}"\s\{-}\)*>\)\@<=\(\(<\/Annotation\)\@!\_.\)\{-}"MATCH\_.\{-}\(<\/Annotation>\)\@=
让我们分解一下......
第 1 组是 。它与 Attribute 元素的 start-tag 匹配。组 2 嵌入在组 1 中,与属性匹配,可以重复 0 次或多次。<Annotation\(\s*\w\+="[^"]\{-}"\s\{-}\)*>
第 2 组是 。这些作品中的大多数是常用的;最不寻常的是 ,这意味着非贪婪的重复(在兼容 Perl 的正则表达式中)。最后的非贪婪空格匹配对性能很重要;如果没有它,Vim 将尝试各种可能的方法在组 2 的末尾和组 2 的下一个出现的开头之间的属性之间拆分空格。\s*\w\+="[^"]\{-}"\s\{-}
\{-}
*?
\s*
\s*
第 1 组后跟 。这是一个零宽度的正向后视。它可以防止将开始标记包含在匹配的文本中(例如,对于 s///)。\@<=
第 3 组是 。它包括组 4,它与 Attribute end-tag 的开头匹配。是零宽度的负前瞻,与任何字符(包括换行符)匹配。总之,这对任何字符进行分组,但属性结束标记开始的地方除外。第 3 组后面跟着一个非贪婪的重复标记,以便它与 MATCH 之前的最小文本块匹配。如果要使用组 3 代替,则匹配的文本可以包含不包含 MATCH 的 Annotation 元素的结束标记,并继续到 MATCH 的下一个 Annotation 元素。(试试吧。\(<\/Annotation\)\@!\_.
\@!
\_.
\{-}
\_.
接下来的一点很简单:在结束标记之前找到 MATCH 和最少数量的其他字符。
第 5 组很简单:它是结束标签。 是一个零宽度的正前瞻,此处包含它的原因与 for the start-tag 相同。我们必须重复而不是使用,因为不会捕获具有零宽度修饰符的组。\@=
\@<=
<\/Attribute
\4
评论
<