Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Regex 正则表达式-零宽度';单词边界';使交替模式正确匹配_Regex_Perl - Fatal编程技术网

Regex 正则表达式-零宽度';单词边界';使交替模式正确匹配

Regex 正则表达式-零宽度';单词边界';使交替模式正确匹配,regex,perl,Regex,Perl,关于: 如果输入: home/////test/tmp/ 以及所需的转换: /home/test/tmp/ (和其他文件路径类似的模式,需要尾随斜杠和前导斜杠,但不能使用双精度。例如,/home/test/tmp/通过,但/home/test/tmp获得尾随斜杠,等等。) 使用三重正则表达式 s,^/*,/,; #prefix s,/*$,/,; #suffix s,/+,/,g; #double slashes anywhere else. 给出了正确的结果: #!/usr/bin/

关于:

如果输入:

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
放在那里是否可能会有问题

这里有一个单独的正则表达式来完成所有操作:

s='home/////test/tmp/'
perl -pe 's~^(?!/)|(?<!/)$|/{2,}~/~g' <<< "$s"
/home/test/tmp/

s='home/test/tmp'
perl -pe 's~^(?!/)|(?<!/)$|/{2,}~/~g' <<< "$s"
/home/test/tmp/
s='home///test/tmp/'

perl-pe的~^(?!/)|(?原因是,
/g
下的
/+
交替匹配最后一个斜杠–然后由于锚的存在而继续搜索。它从最后一个替换后的位置继续,因此在最后一个斜杠之后。该搜索匹配
$
处的零斜杠,并添加
/

我们可以通过

perl -wE'
    $_ = "home/dir///end/"; 
    while (m{( ^/* | /+ | /*$ )}gx) { say "Got |$1| at ", pos }
'
打印(为了可读性,在…
处对齐

数字不同,因为它们指的是中间字符串中的位置,其中最后两个

... Got |/| at 14 Got || at 15
您的单个正则表达式将
“/”
转换为
“/”
,出于类似的原因。正如其他人回答您的问题一样,我想我应该指出,您最初的“使用三重正则表达式”给出的正确结果实际上是有缺陷的。您的前缀和后缀都在字符串的开头或结尾处寻找零个或多个斜杠,而实际上您希望在因此,对于前缀,应该更正确地查找:-s,^([^/]),/\1,…。这将检查前面是否有斜杠,然后再加上找到的字符。@Sobrique我在我的帖子中添加了我认为比原来的口头陈述更清楚的内容。如果你看不到更改,请告诉你。 Got || at 0 Got |/| at 5 Got |///| at 11 Got |/| at 15 Got || at 15
s{( ^/* | /+ | /*$ )}{ say "Got |$1| at ", pos; q(/) }egx
... Got |/| at 14 Got || at 15
$_ = '/' . (join '/', grep { /./ } split '/', $_) . '/'  for @paths;