2014-08-28 49 views
1

我正在尝试编写匹配字符串后跟可选模式的正则表达式。匹配文本后跟可选模式

这里就是我想匹配match/string

/any/path/match/string 
/any/path/match/string/pattern 
/any/path/match/string/pattern/something/else 

/any/path/pattern是静态的文字和match/string可以是任何文字的三个输入字符串的例子。

我已经试过这

print $1 if m,/any/path/(.+)(?=/pattern/)?, 

,但它在整个输入字符串,因为.+是贪婪匹配。

+0

语法像'(?= ...)'是一个空操作。那么......“*之后是一个可选模式*”,没有什么意义。你想做什么?请给出具体的例子。 – 2014-08-28 23:14:06

+0

基本上我试图匹配“/任何/路径”和“/ pattern”之间的文本,其中“/ pattern”可能存在或不存在于输入字符串中。 – quicoju 2014-08-28 23:17:27

+0

问题是,因为'match/string'可能是*“任何文本”*,所以它可能是'/ match/string/pattern/something/else'。如果你正确地定义你想要做的事情,那么代码将更加明显 – Borodin 2014-08-29 01:42:42

回答

1

正如你已经猜到,你的问题是贪婪匹配。

记住,如果你有一个正则表达式的麻烦,你总是可以打破逻辑到步骤:

print +(split m{/pattern\b}, $1)[0] if m{^/any/path/(.+)}; 

为此使用单一的正则表达式,虽然做的,有两种做法:

  1. 限制任何字符.可以通过在其之前放置负面预测声明来匹配。
  2. 使用与结束边界联合的非贪婪匹配。

下面演示了这两种方法:

use strict; 
use warnings; 

while (<DATA>) { 
    print "\nString = $_"; 

    if (m{^/any/path/((?:(?!/pattern\b).)*)}x) { 
     print " Neg Lookahead  - $1\n" 
    } 

    if (m{^/any/path/(.*?)(?:/pattern\b|$)}x) { 
     print " Nongreedy with bound - $1\n" 
    } 
} 
__DATA__ 
/any/path/match/string 
/any/path/match/string/pattern 
/any/path/match/string/pattern/something/else 

输出:

String = /any/path/match/string 
    Neg Lookahead  - match/string 
    Nongreedy with bound - match/string 

String = /any/path/match/string/pattern 
    Neg Lookahead  - match/string 
    Nongreedy with bound - match/string 

String = /any/path/match/string/pattern/something/else 
    Neg Lookahead  - match/string 
    Nongreedy with bound - match/string 
+1

'print +(split m {/ pattern \ b},$ 1)[0] if m {^/any/path /(.+)} '?我不知道那是干嘛的! – Borodin 2014-08-29 01:46:02

0

你可以使用这个表达式:

/any/path/(\w+?/\w+)/pattern|/any/path/(\w+?/\w+)$ 

Working demo

enter image description here