仅在 Perl 正则表达式中匹配最后一次出现的位置

问题描述 投票:0回答:2
/1.1/s/1/-/g

我正在做学校作业以参考实现 sed 命令。我得到这个字符串来匹配“/1/-/”。我有实验

$str =~ m{/[^/]*/[^/]*/}g;

但结果是/1.1/s/。我怎样才能只得到“/1/-/” 有人可以帮助我吗?

regex perl
2个回答
0
投票

使用

/[^/]*/[^/]*/(?=[^/]*$)

参见证明

解释

--------------------------------------------------------------------------------
  /                        '/'
--------------------------------------------------------------------------------
  [^/]*                    any character except: '/' (0 or more times
                           (matching the most amount possible))
--------------------------------------------------------------------------------
  /                        '/'
--------------------------------------------------------------------------------
  [^/]*                    any character except: '/' (0 or more times
                           (matching the most amount possible))
--------------------------------------------------------------------------------
  /                        '/'
--------------------------------------------------------------------------------
  (?=                      look ahead to see if there is:
--------------------------------------------------------------------------------
    [^/]*                    any character except: '/' (0 or more
                             times (matching the most amount
                             possible))
--------------------------------------------------------------------------------
    $                        before an optional \n, and the end of
                             the string
--------------------------------------------------------------------------------
  )                        end of look-ahead

0
投票

请记住,正则表达式引擎通常更喜欢最左边的最长匹配。

查找模式的最后一个匹配项的正则表达式习惯用法是在其前面加上

^.*
前缀。量词是贪婪的,因此
.*
从目标字符串的左端开始,吞噬右端的所有内容,并返回尽可能少的内容以使匹配成功。

前导

^
锚点并不是绝对必要的,但我发现它更能唤起人们对正在发生的事情的回忆。

适用于您的案例变成

$str = "/1.1/s/1/-/g";
if ($str =~ m{^.*(/[^/]*/[^/]*/)}) {
  print "Last match: [$1]\n";
}
else {
  print "No match: $str\n";
}

在线尝试或执行下面等效的 JavaScript 片段。无论哪种方式,输出都是

Last match: [/1/-/]

const str = '/1.1/s/1/-/g';
const pattern = new RegExp('^.*(/[^/]*/[^/]*/)');
let m;

if ((m = str.match(pattern)) !== null) {
  console.log(`Last match: [${m[1]}]`);
}
else {
  console.log(`No match: - ${str}`);
}

© www.soinside.com 2019 - 2024. All rights reserved.