2011-04-15 51 views
3

我试图运行下面的搜索不工作(加上一些以匹配换行符通过添加在Perl/s标志或在vim与\_.取代它。):关闭贪婪在这个表达式

/<output_channels>.*(?=Story).*?<\/output_channels>/ 

但是?没有像往常那样关掉贪婪 - 任何人都可以解释为什么?如果我失去了一些东西明显

<output_channels> 
    <output_channel>RSS</output_channel> 
    <output_channel>Story</output_channel> 
</output_channels> 

<output_channels> 
    <output_channel>RSS</output_channel> 
</output_channels> 

对不起:例如,下面的文件,而不是仅仅是第一要素的全部内容相匹配。

+0

那么,你使用Perl的正则表达式或vim的正则表达式搜索/替换? – BoltClock 2011-04-15 09:54:42

+0

你给的RE使用了几个在vim中不起作用的元素。不知道你是否意识到这一点。检查[':help perl-patterns'](http://vimdoc.sourceforge.net/htmldoc/pattern.html#perl-patterns)获取差异列表。你在用什么来做搜索? – intuited 2011-04-15 09:58:29

+0

@BoltClock两者兼得。最终我会使用perl,但我发现在vim中使用正则表达式更快。 – tog22 2011-04-15 11:21:22

回答

1

我把你的示例文本到一个Vim缓冲区,然后执行命令

:%!perl -e '$text = join("", <STDIN>); $text =~ /<output_channels>.*(?=Story).*?<\/output_channels>/s; print $&;' 

结果仅仅是XML的第一个块。我认为这是你想要的?

请注意,我逃过了正则表达式中的/。除此之外,它与您的问题中给出的是相同的。

还要注意的是等效的VIM RE会(测试工作):

<output_channels>\_.*\(story\)\@=\_.\{-}<\/output_channels> 

为Perl和VIM的RE之间的差异破败见:help perl-patterns

另外请注意parsing heirarchical markup with regexps has been known to reawaken ancient demons

+0

谢谢。对于什么是值得的,你的vim RE不起作用 - 在vim中测试的时候能够使用它我会很高兴,但是perl RE是我真正需要的。 – tog22 2011-04-15 12:41:43

+0

...虽然你可以解释为什么当我切换到负向前视图时,以下功能无法按预期工作(仅捕获文件中的第二个元素)。我有一种感觉,它与第一个的贪婪有关。*但是当我切换这个时。*?我找到了一个操作员。有没有一种方法可以捕获不包含'Story'的元素,还是使用regexps以外的工具更好? /\_.*\(story\)\@/ – tog22 2011-04-15 15:13:42

+0

@ tog22:我刚刚测试了vim RE,发现它可以同时适用于两者['/'](http://vimdoc.sourceforge.net/htmldoc/pattern.html#/)和['matchstr()'](http://vimdoc.sourceforge.net/htmldoc/eval.html#matchstr ())。请注意,在vim中,你不需要(也不能)用'/'字符来包围RE;我只是让它们与perl-ish版本类似。我把它们拿出来了。 – intuited 2011-04-15 17:13:07

1

您的正则表达式中的第一个.*仍然是贪婪的。第二个之后你只添加了?

+4

但是,在这种情况下,前瞻将涵盖'(?=故事)' – Seth 2011-04-15 10:05:03

+0

谢谢,但正如塞思指出,这里没有必要。 – tog22 2011-04-15 11:38:46