正则表达式:确认是否匹配了可选部分

时间:2018-07-30 19:55:55

标签: regex perl

我有一个字符串,该字符串可以有两种形式,但每次都用哪种形式是未知的:

hello world[0:10];hello world;

可能带有或没有带有数字的方括号。两个词(hello和world)可以不同。如果有括号和数字,则第一个数字始终为0,第二个数字(10)有所不同。

我需要捕获第一个单词(你好),如果有,请捕获第二个数字(10)。我还需要知道它是哪种形式的字符串。

hello world[0:10];我将捕获{hello,10,form1},而hello world;我将捕获{hello,form2}。我并不在乎“表单”的格式,我只需要能够区分即可。可以是一点(1 = form1、0 = form2),结构(form1将我置于一个范围内,而form2将我置于另一个范围内)等等。


我目前有以下(正在运行)正则表达式:

/(\w*) \s \w* (?:\[0:(\d*)\])?;/x

这给了我$1 = hello并可能给我$2 = 10我现在只需要知道方括号中的数字是否存在。这将重复很多次,所以我不能假设$2 = undef进入正则表达式。 $2也可能连续几遍是同一件事,所以我不能只是在正则表达式前后查找$2中的变化。

到目前为止,我最好的解决方案是两次运行该正则表达式,第一次使用方括号,第二次不使用方括号:

if( /(\w*) \s \w* \[0:(\d*)\];/x ) {...}
elsif( /(\w*) \s \w*;/x ) {...}

这似乎效率很低而且很不优雅,所以我想知道是否有更好的方法?

1 个答案:

答案 0 :(得分:4)

您可以使用?来匹配正则表达式的各个部分。然后,您可以将输出直接捕获为正则表达式的返回值。

my $re = qr{ (\w*) \s* (?:\[0:(\d+)\])?; }x;
if( my($word, $num) = $line =~ $re ) {
    say "Word: $word";
    say "Num: $num" if defined $num;
}
else {
    say "No match";
}

(?:\[0:(\d+)\])?可能[0:\d+](?:)使分组无法捕获,因此仅捕获了\d+

$1$2也是安全使用的,它们在每次匹配时都会重置,但是使用词法变量会使情况更明确。