代码之家  ›  专栏  ›  技术社区  ›  noah

regex:确认是否匹配了可选部分

  •  1
  • noah  · 技术社区  · 6 年前

    我有一个字符串,可以有两种形式,但每次都不知道是哪种形式:

    hello world[0:10]; hello world;

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

    我需要捕获第一个单词(hello),如果它存在,第二个数字(10)。我还需要知道它是哪种弦形式。

    你好世界[0:10]; 我会捕捉{hello,10,form1},然后 你好世界; 我会捕捉{你好,表格2}。我真的不在乎“表单”的格式,我只需要能够区分。它可以是位(1=form1,0=form2)、结构(form1将我放在一个范围内,form2放在另一个范围内)等。


    我现在有 (正在工作) 正则表达式:

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

    这给了我 $1 = hello 而且可能 $2 = 10 . 我现在只需要知道括号内的数字是否存在。这会重复很多次,所以我不能假设 $2 = undef 进入regex。 $2 可能连续几次都是一样的,所以我不能就这样 2美元 在正则表达式之前和之后。

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

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

    这看起来效率很低,也不优雅,所以我想知道是否有更好的方法?

    1 回复  |  直到 6 年前
        1
  •  4
  •   Schwern    6 年前

    你可以用 ? 选择匹配regex的部分。然后可以直接从regex中捕获输出作为返回值。

    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 也是安全的,它们在每个匹配中被重置,但是使用词汇变量使事情更加明确。