我的脚本接收文件路径,我想将一个目录附加到路径的末尾。问题是我想知道参数是否有一个尾部斜杠是不可知的。例如:
$ perl myscript.pl /path/to/dir
/path/to/dir/new
$ perl myscript.pl /path/to/dir/
/path/to/dir/new
我尝试了$path =~ s/\/?$/\/new/g
,但如果存在斜杠,则会导致加倍/new
:
$ perl myscript.pl /path/to/dir
/path/to/dir/new/new
$ perl myscript.pl /path/to/dir
/path/to/dir/new
怎么了?
答案 0 :(得分:2)
因为/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;
这为您提供了一种独立于平台的方式来分割和连接路径元素,并且不依赖于正则表达式匹配 - 它可能有多种破坏方式(例如您找到的方式)。
答案 1 :(得分:1)
删除/g
修饰符:
$path =~ s/\/?$/\/new/
工作正常
您只想修改最后添加一个“新”,因此使用/g
修饰符毫无意义。
另请注意,您可以为正则表达式使用不同的分隔符:
$path =~ s{ /? $}{/new}x;
有点清楚。