引用:perl string catenation and substitution in a single line?
给定输入:
home/////test/tmp/
以及所需的转换为:
/home/test/tmp/
(和其他类似模式的文件路径,需要尾部和前导斜杠,但没有双斜杠。例如 /home/test/tmp/
通过,但 /home/test/tmp
得到尾部斜杠等)
使用三重正则表达式;
s,^/*,/,; #prefix
s,/*$,/,; #suffix
s,/+,/,g; #double slashes anywhere else.
给我们正确的结果:
#!/usr/bin/env perl
use strict;
use warnings;
my $str = 'home/////teledyne/tmp/';
$str =~ s,^/*,/,; #prefix
$str =~ s,/*$,/,; #suffix
$str =~ s,/+,/,g; #double slashes anywhere else.
print $str;
但如果我尝试使用交替组合这些模式,我会得到:
s,(^/*|/+|/*$),/,g
这看起来像它应该 工作......实际上没有,我得到了一个双斜杠。
但是添加零宽度匹配,效果很好:
s,(^/*|/+|\b/*$),/,g;
任何人都可以帮助我了解交替组中发生的不同情况,是否有可能将 \b
留在其中?
最佳答案
原因是 /g
下的 /+
交替匹配最后一个斜杠——然后由于 anchor 的存在,搜索继续进行。它从最后一个替换之后的位置继续,也就是在最后一个斜线之后。该搜索匹配 $
处的零斜杠并添加 /
。
我们可以通过
perl -wE'
$_ = "home/dir///end/";
while (m{( ^/* | /+ | /*$ )}gx) { say "Got |$1| at ", pos }
'
打印(为了便于阅读,对齐 at ...
)
Got || at 0 Got |/| at 5 Got |///| at 11 Got |/| at 15 Got || at 15
With the actual substitution
s{( ^/* | /+ | /*$ )}{ say "Got |$1| at ", pos; q(/) }egx
数字不同,因为它们指的是中间字符串中的位置,其中最后两个
... Got |/| at 14 Got || at 15
are telling.
I don't see what can go wrong with having \b
, as in the question or as /*\b$
.
This is an interesting question, but I'd like to add that all these details are avoided by
$_ = '/' . (join '/', grep { /./ } split '/', $_) . '/' for @paths;
关于正则表达式 - 零宽度 'word boundary' 使交替模式正确匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43235471/