我需要在<Annotation>
和</Annotation>
之间获取所有文字,其中出现单词MATCH
。我怎么能在VIM中做到这一点?
<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>
答案 0 :(得分:4)
首先,免责声明:任何使用正则表达式对XML进行切片和切块的尝试都是脆弱的;一个真正的XML解析器会做得更好。
模式:
\(<Annotation\(\s*\w\+="[^"]\{-}"\s\{-}\)*>\)\@<=\(\(<\/Annotation\)\@!\_.\)\{-}"MATCH\_.\{-}\(<\/Annotation>\)\@=
让我们分解......
第1组是<Annotation\(\s*\w\+="[^"]\{-}"\s\{-}\)*>
。它匹配Attribute元素的start-tag。嵌入在组1中的组2与属性匹配,可以重复0次或更多次。
第2组是\s*\w\+="[^"]\{-}"\s\{-}
。大多数这些作品都是常用的;最不寻常的是\{-}
,这意味着非贪婪的重复(Perl兼容的正则表达式中的*?
)。最后的非贪婪空白匹配对于性能很重要;如果没有它,Vim将尝试一切可能的方法来分割第2组末尾的\s*
和第2组最后一次出现时的\s*
之间的属性之间的空白。
第1组之后是\@<=
。这是一个零宽度的正面观察。它可以防止start-tag包含在匹配的文本中(例如,对于s ///).
第3组是\(<\/Annotation\)\@!\_.
。它包括Group 4,它匹配Attribute end-tag的开头。 \@!
是零宽度否定前瞻,\_.
匹配任何字符(包括换行符)。这些组一起匹配除属性结束标记开始之外的任何字符。第3组之后是非贪婪的重复标记\{-}
,以便它匹配MATCH之前的最小文本块。如果您使用\_.
而不是Group 3,匹配的文本可能包含不包含MATCH的Annotation元素的结束标记,并继续使用MATCH进入下一个Annotation元素。 (试试吧。)
下一位很简单:在结束标记之前找到MATCH和最少数量的其他字符。
第5组很简单:它是结束标记。 \@=
是零宽度正向前瞻,其中包含的原因与起始标记的\@<=
相同。我们必须重复<\/Attribute
而不是使用\4
,因为未捕获具有零宽度修饰符的组。
答案 1 :(得分:3)
是否必须在vim中完成?你可以作弊,并打开第二个窗口,你可以用更多/更少的东西来管理你在vim中要去的行号吗?
- 编辑 -
我从未在vi [m]中进行过多行匹配/搜索。但是,要在另一个窗口作弊:
perl -n -e 'if ( /<tag/ .. /<\/tag/)' -e '{ print "$.:$_"; }' file.xml | less
将显示“tag”(或其他较长匹配名称)的元素/块,其中包含行号,然后您可以在每个块中搜索其他文本。
足够近?
- 编辑 -
在“less”内,输入
/MATCH
搜索MATCH的出现次数。在左边距将是该实例(在目标元素/标签内)的行号。
在vi [m]内,输入
:n
其中“n”是所需的行号。
当然,如果你真正想做的是某种搜索/猛拉/替换,那就更复杂了。那时,awk / perl / ruby(或类似的符合你的口味的东西......或xsl?)实际上是你应该用于转换的工具。