我正在使用以下正则表达式模式:
.*(?<line>^\s*Extends\s+#(?<extends>[_A-Za-z0-9]+)\s*$)?.*
以及以下文字:
Name #asdf
Extends #extendedClass
Origin #id
我不明白的是,两个捕获的组结果(线条和扩展名)都是空的,但是当我从表达式中删除最后一个问号时,捕获了这些组。
该行组必须是可选的,因为扩展行并不总是存在。
我使用此表达式创建了一个小提琴,可通过https://regexr.com/4rekk
访问编辑
我忘了提到我在表达式中使用了多行和dotall标志。
答案 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);