2013-11-04 33 views
1

该代码有点复杂,但我简化了一下。我知道我可以很容易地做到这一点:Perl s /../../不按预期工作

$svn_module s#.*/##; 

并拉出模块的结束。但令人奇怪的是怎么回事:

#! /usr/bin/env perl 
use strict; 
use warnings; 

my $svn_module = "http://svn.vegicorp.net/svn/trunk/SessionController"; 
print qq(DEBUG: svn_module = "$svn_module"\n); 
$svn_module =~ s#^.*(branches/.+?/)|(trunk)/##; 
print qq(DEBUG: svn_module = "$svn_module"\n); 

此打印:

DEBUG: svn_module = "http://svn.vegicorp.net/svn/trunk/SessionController" 
DEBUG: svn_module = "http://svn.vegicorp.net/svn/SessionController" 

不过,我期待:

DEBUG: svn_module = "http://svn.vegicorp.net/svn/trunk/SessionController" 
DEBUG: svn_module = "SessionController" 

为什么我的替换表达式删除trunk/,但不休息的字符串高达trunk/

顺便说一句,增加一个额外的括号的帮助:

$svn_module =~ s#^.*((branches/.+?/)|(trunk))/##; 

会工作。

顺便说一下,这是Perl 5.8.8。这是一个服务器,几乎是我所坚持的版本。

回答

2

我想你自己回答了这个问题。 |运算符的优先级最低,因此添加括号是解决方案。

+0

好的,我不确定你是否回答了我的问题。显然,额外的一组或括号是有效的。但是,在阅读你的答案后,我想我明白了。我说基本上我是匹配'^。* branches /.+?/'或'trunk'。不像我想的那样,我从一开始就匹配整个字符串到'trunk'。 –

+0

@DavidW。正确 – ysth

4

或许应该是这样

s#^.*(?:branches/.+?/|trunk)/##;

因为,其他的方式,这是一个单交替其中^.*不是第二交替(即匹配的那一个)的一部分

^.* 
    (branches/ .+? /) 
| 
    (trunk) 

编辑:扩大新的正则表达式在你原来的正则表达式来解释

^      # Beginning of string anchor 
.*      # Optional match as many as possible non-newline character until .. 
(?:      # Start non-capture grouping 
     branches/ .+?/  # 'branches' plus '/' plus 1 or more chars plus '/' 
    | trunk     # Or, 'trunk' 
)      # End grouping 

相当于是这个

^.* 
    (branches/ .+? /) 
| 
^.* 
    (trunk) 
+0

我想我的困惑与我的'^ *'锚做。我会假设这是从字符串的开头匹配的,但显然它不是。 –

+0

'?:'并不是真的有必要,因为我没有进行组更换,但我想它不会受伤。真正的问题是为什么我的主播不工作。发生了什么是由于我误读优先。我实际上是用'|'或'^。* branches /.+?/'**或**'trunk'匹配的。 –

+0

@David W. - (?:)'是一个扩展名,表示非捕获分组。因为您只是在整个比赛中进行替换(默认),所以捕获分组对于您的情况并不是必要的。为什么你的主播不起作用的真正答案是它不是你希望它适用的两个改变的因素。正则表达式几乎不是操作符优先级的语言,只是构造(即:元字符)。 – sln

1

也许我在这里错过了一些东西,大卫,而不是取代所有的东西到最后一部分,你想得到你想要的东西,为什么不捕获只是最后一部分?

use strict; 
use warnings; 

my $svn_module = "http://svn.vegicorp.net/svn/trunk/SessionController"; 
my ($end_module) = $svn_module =~ /([^\/]+)$/; 
print $end_module; 

输出:

SessionController 
+0

我想确保在那里有一个'trunk'或'branches /.*?/',以确保我正在查看项目,而不是在某个目录或标签内。否则,我可以完成你所提到的。 –

+0

@DavidW。 - 啊。那么为什么不相应地调整捕获,例如'/((?: trunk | branches)。+)/',而不是's ###'? – Kenosis