为什么这些JavaScript正则表达式捕获圆括号而不是单词后面的后缀

Why do these JavaScript regular expression capture parenthesis snag entire line instead of the suffixes appended to a word?

本文关键字:单词 后缀 圆括号 JavaScript 正则表达式 为什么      更新时间:2023-09-26

有人能告诉我为什么我的简单表达式没有捕获可选的任意长度。hello后面的后缀片段,匹配完整的行吗?

相反,它匹配整行(hello.aa.b再见),而不是捕获括号的内容。

使用此代码(请参阅JSFIDDLE):

//var line = "hello goodbye";            // desired: suffix null
//var line = "hello.aa goodbye";         // desired: suffix[0]=.aa
var line = "hello.aa.b goodbye";         // desired: suffix[0]=.aa suffix[1]=.b
var suffix = line.match(/^hello('.[^'.]*)*'sgoodbye$/g);

我已经研究这个简单的表达式三个多小时了,我开始相信我对捕捉的工作原理有一个根本的误解:不是有一个"光标"一个字符一个字符地吞噬每一行,并捕捉括号内的内容吗()?

我最初是从Perl开始的,然后是PHP。当我开始使用JavaScript时,我曾经遇到过这种情况。

在JavaScript中,GLOBAL匹配不会生成多维数组。换句话说,在GLOBAL匹配中只有match[0](没有子模式)。

请注意,后缀[0]与整个字符串匹配。

试试这个:

//var line = "hello goodbye";            // desired: suffix undefined
//var line = "hello.aa goodbye";         // desired: suffix[1]=.aa
var line = "hello.aa.b goodbye";         // desired: suffix[1]=.aa suffix[2]=.b
var suffix = line.match(/^hello('.[^.]+)?('.[^.]+)?'s+goodbye$/);

如果你必须使用全局匹配,那么你必须首先捕获整个字符串,然后运行第二个RegEx来获得子模式。

祝你好运:)

更新:进一步解释

如果每个字符串只有一个可匹配的模式(如var line = "hello.aa.b goodbye";)然后你可以使用我上面发布的模式(没有全局修饰符)

如果一个刺痛有不止一个可匹配的模式,那么看看下面的:

// modifier g means it will match more than once in the string
// ^ at the start mean starting with, when you wan the match to start form the beginning of the string
// $ means the end of the string
// if you have ^.....$ it means the whole string should be a ONE match
var suffix = line.match(/^hello('.[^.]+)?('.[^.]+)?'s+goodbye$/g);

var line = 'hello.aa goodbye and more hello.aa.b goodbye and some more hello.cc.dd goodbye';
// no match here since the whole of the string doesn't match the RegEx
var suffix = line.match(/^hello('.[^.]+)?('.[^.]+)?'s+goodbye$/);
// one match here, only the first one since it is not a GLOBAL match (hello.aa goodbye)
// suffix[0] = hello.aa goodbye
// suffix[1] = .aa
// suffix[2] = undefined
var suffix = line.match(/hello('.[^.]+)?('.[^.]+)?'s+goodbye/);
// 3 matches here (but no sub-patterns), only a one dimensional array with GLOBAL match in JavaScript
// suffix[0] = hello.aa goodbye
// suffix[1] = hello.aa.b goodbye
// suffix[2] = hello.cc.dd goodbye
var suffix = line.match(/hello('.[^.]+)?('.[^.]+)?'s+goodbye/g);

我希望这能有所帮助。:)

内部()请不要找。然后找一些空间。和一些字符,最后在外部()查找该空间

重复捕获组将只捕获最后一次迭代。在重复的组周围放置一个捕获组,以捕获所有迭代。

var suffix = line.match(/^hello(('.[^'.]*)*)'sgoodbye$/g);
if (suffix !== null)
    suffix = suffix[1].match(/('.[^'.'s]*)/g)

我建议使用regex101站点。

match方法中使用全局标志不会返回任何捕获组。请参阅规范。

尽管您使用()*,但它只是一个捕获组。*仅定义内容必须在空间到来之前匹配0次或更多次。

正如@EveryEvery所指出的,你可以使用两步走的方法。