因为/g
是“全球性”,并会匹配其多次重复:
#!/usr/bin/env perl
use strict;
use warnings;
#turn on debugging
use re 'debug';
my $path = '/path/to/dir/';
$path =~ s/\/?$/\/new/g;
print $path;
第一替补,正则表达式引擎“左”标志“行结束”后,并不需要匹配可选/
。所以再次匹配。
例如为:
Compiling REx "/?$"
Final program:
1: CURLY {0,1} (5)
3: EXACT </> (0)
5: SEOL (6)
6: END (0)
floating ""$ at 0..1 (checking floating) minlen 0
Matching REx "/?$" against "/path/to/dir/"
Intuit: trying to determine minimum start position...
doing 'check' fbm scan, [0..13] gave 13
Found floating substr ""$ at offset 13 (rx_origin now 12)...
(multiline anchor test skipped)
try at offset...
Intuit: Successfully guessed: match at offset 12
12 <path/to/dir> </> | 1:CURLY {0,1}(5)
EXACT </> can match 1 times out of 1...
13 <path/to/dir/> <> | 5: SEOL(6)
13 <path/to/dir/> <> | 6: END(0)
Match successful!
Matching REx "/?$" against ""
Intuit: trying to determine minimum start position...
doing 'check' fbm scan, [13..13] gave 13
Found floating substr ""$ at offset 13 (rx_origin now 13)...
(multiline anchor test skipped)
Intuit: Successfully guessed: match at offset 13
13 <path/to/dir/> <> | 1:CURLY {0,1}(5)
EXACT </> can match 0 times out of 1...
13 <path/to/dir/> <> | 5: SEOL(6)
13 <path/to/dir/> <> | 6: END(0)
Match successful!
Matching REx "/?$" against ""
Intuit: trying to determine minimum start position...
doing 'check' fbm scan, [13..13] gave 13
Found floating substr ""$ at offset 13 (rx_origin now 13)...
(multiline anchor test skipped)
Intuit: Successfully guessed: match at offset 13
13 <path/to/dir/> <> | 1:CURLY {0,1}(5)
EXACT </> can match 0 times out of 1...
13 <path/to/dir/> <> | 5: SEOL(6)
13 <path/to/dir/> <> | 6: END(0)
这是因为$
是零宽度位置锚。如果没有匹配,\/?
也是如此。一旦模式一直消耗到尾部/
并替换..然后正则表达式引擎继续(因为你告诉它与/g
),并找到只剩$
,因为这仍然是行的末尾。这仍然是一个有效的替代。
但是,为什么不改用File::Spec
:
#!/usr/bin/env perl
use strict;
use warnings;
use File::Spec;
use Data::Dumper;
my $path = '/path/to/dir/';
my @dirs = File::Spec->splitdir($path);
print Dumper \@dirs;
$path = File::Spec->catdir(@dirs, "new");
print $path;
这为您提供了拆分和联接路径元素一个独立于平台的方式,并且不依赖于正则表达式匹配 - 这有各种方式就可以打破(如你找到的那个)。
谢谢。这工作。你能解释发生了什么吗? – ewok
'$'不会消耗“字符串的结尾”,它只是一个断言(它声称“字符串的末尾在这里”)。所以用'/?',你的正则表达式在两个位置匹配:首先匹配'/'后跟行尾,然后如果匹配* nothing *紧跟行尾。明白了吗? – Dada
排序,但为什么不会导致无限循环? – ewok