首页 > 解决方案 > Perl 正则表达式:为什么未捕获可选部分?

问题描述

我正在尝试捕获最后一部分是可选的匹配项,但如果存在则应该被捕获。但如果它是可选的 using (...)?,则不会被捕获。

例如,使用以下 2 行:

some text and number 18
some other text

如果我看到“数字 18”,我想总是捕捉“一些”,并捕捉“18”。

使用/(some).*?(?:number (\d+))/, 当然适用于第一行,但不适用于第二行:

$ echo "some text and number 18" | perl -nle '/(some).*?(?:number (\d+))/ && print join("\n", $1, $2)'
some
18
$ echo "some other text" | perl -nle '/(some).*?(?:number (\d+))/ && print join("\n", $1, $2)'
$

但是当/(some).*?(?:number (\d+))?/用于使最后一部分可选时,总是会捕获第一个匹配项,但数量不是:

$ echo "some text and number 18" | perl -nle '/(some).*?(?:number (\d+))?/ && print join("\n", $1, $2)'
some

$ echo "some other text" | perl -nle '/(some).*?(?:number (\d+))?/ && print join("\n", $1, $2)'
some

$ 

如何捕获可选部分?

标签: regexperl

解决方案


您可以使用

/(some)(?:.*?number (\d+))?/

请参阅正则表达式演示。细节:

  • (some)- 第 1 组:some
  • (?:.*?number (\d+))?- 一个可选的非捕获组,将至少尝试一次,并将尝试匹配 1 或 0 次出现
    • .*?- 除换行符以外的任何 0+ 字符,尽可能少
    • number - 一个number 字符串
    • (\d+)- 第 2 组:1+ 位数

查看在线演示

perl -nle '/(some)(?:.*?number (\d+))?/ && print join("\n", $1, $2)' <<< "some text and number 18"
# some
# 18
perl -nle '/(some)(?:.*?number (\d+))?/ && print join("\n", $1, $2)' <<< "some other text"
# some

推荐阅读