正则表达式未捕获可选组

时间:2019-12-30 10:04:27

标签: regex

我正在使用以下正则表达式模式:

.*(?<line>^\s*Extends\s+#(?<extends>[_A-Za-z0-9]+)\s*$)?.*

以及以下文字:

   Name                #asdf
   Extends             #extendedClass
   Origin              #id

我不明白的是,两个捕获的组结果(线条和扩展名)都是空的,但是当我从表达式中删除最后一个问号时,捕获了这些组。

该行组必须是可选的,因为扩展行并不总是存在。

我使用此表达式创建了一个小提琴,可通过https://regexr.com/4rekk

访问

编辑

我忘了提到我在表达式中使用了多行和dotall标志。

1 个答案:

答案 0 :(得分:0)

已经提到过,当您将.*组设为可选时,前导(?<line>)会捕获所有内容。以下内容与您的问题没有直接关系,但可能是有用的信息(如果不是,请忽略):

您需要在其他地方小心。您正在使用^$来匹配行的开头和结尾以及字符串的开头和结尾。但是$字符不会占用标记行尾的换行符。所以:

'Line 1\nLine 2'.match(/^Line 1$^Line 2/m)返回null

同时

'Line 1\nLine 2'.match(/^Line 1\n^Line 2/m)返回一个匹配项

因此,在您的情况下,如果您试图捕获所有三行,其中任何一行都是可选的,则可以为其中的一行编写正则表达式,如下所示,以确保您使用了换行符:

/(?<line>^\s*Extends\s+#(?<extends>[_A-Za-z0-9]+)[^\S\n]*\n)?/ms

在您指定\s*$的地方,我有[^\S\n]*\n[^\S\n]*是双重否定词,表示一个或多个 non 非空白字符,但不包括换行符。因此它将消耗除换行符以外的所有空白字符。如果要查找示例中的三行中的任何一行(任意或全部是可选的),则应使用以下代码段来实现。我使用了RegExp函数来创建正则表达式,以便可以将其拆分为多行。不幸的是,它以字符串作为参数,因此某些反斜杠字符必须加倍:

let s = `   Name                #asdf
   Extends             #extendedClass
   Origin              #id
`;


let regex = new RegExp(
    "(?<line0>^\\s*Name\\s+#(?<name>[_A-Za-z0-9]+)[^\\S\\n]*\\n)?" +
    "(?<line>^\\s*Extends\\s+#(?<extends>[_A-Za-z0-9]+)[^\\S\\n]*\\n)?" +
    "(?<line2>^\\s*Origin\\s+#(?<id>[_A-Za-z0-9]+)[^\\S\\n]*\\n)?",
    'm'
);


let m = s.match(regex);
console.log(m.groups);

上述代码段在Firefox下似乎有问题(无效的正则表达式标志“ s”标记在上面的代码段中不存在的行上)。参见following regex demo

并且没有命名的捕获组:

let s = `   Name                #asdf
   Extends             #extendedClass
   Origin              #id
`;


let regex = new RegExp(
    "(^\\s*Name\\s+#([_A-Za-z0-9]+)[^\\S\\n]*\\n)?" +
    "(^\\s*Extends\\s+#([_A-Za-z0-9]+)[^\\S\\n]*\\n)?" +
    "(^\\s*Origin\\s+#([_A-Za-z0-9]+)[^\\S\\n]*\\n)?",
    'm'
);


let m = s.match(regex);
console.log(m);