正则表达式 - 零宽度 'word boundary' 使交替模式正确匹配

标签 regex perl

引用: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/

相关文章:

perl - 如何为 Selenium Grid 2 设置 Chrome 驱动程序(Perl 绑定(bind))?

regex - 如何在 Elixir 中找出整个字符串是否为大写?

javascript - 正则表达式:匹配各种维度模式

python - django 的 url 正则表达式如何工作

java - 查找字符串格式的数字中的字符

multithreading - Perl MCE 将哈希数据返回给主进程

Javascript:如何从值中删除字符的出现?

perl - 在 Perl 中使用切片初始化一组哈希键

linux - Perl 中不区分大小写的 GREP

html - 在perl中刷新没有 "Confirm Form Resubmission"的浏览器