JavaScript正则表达式和子匹配

时间:2022-12-21 11:25:42

Why do Javascript sub-matches stop working when the g modifier is set?

为什么在设置g修饰符时Javascript子匹配停止工作?

var text = 'test test test test';

var result = text.match(/t(e)(s)t/);
// Result: ["test", "e", "s"]

The above works fine, result[1] is "e" and result[2] is "s".

上面的工作很好,结果[1]是e,结果[2]是s。

var result = text.match(/t(e)(s)t/g);
// Result: ["test", "test", "test", "test"]

The above ignores my capturing groups. Is the following the only valid solution?

以上这些忽略了我的捕捉组。下面是唯一有效的解决方案吗?

var result = text.match(/test/g);
for (var i in result) {
    console.log(result[i].match(/t(e)(s)t/));
}
/* Result:
["test", "e", "s"]
["test", "e", "s"]
["test", "e", "s"]
["test", "e", "s"]
*/

1 个解决方案

#1


91  

Using String's match() function won't return captured groups if the global modifier is set, as you found out.

如果设置了全局修饰符,那么使用String的match()函数将不会返回捕获的组,正如您所发现的那样。

In this case, you would want to use a RegExp object and call its exec() function. String's match() is almost identical to RegExp's exec() function…except in cases like these. If the global modifier is set, the normal match() function won't return captured groups, while RegExp's exec() function will. (Noted here, among other places.)

在本例中,您希望使用RegExp对象并调用它的exec()函数。String's match()几乎与RegExp的exec()函数相同……但在这种情况下除外。如果设置了全局修饰符,那么普通的match()函数不会返回捕获的组,而RegExp的exec()函数会返回。(这里有提到,还有其他地方。)

Another catch to remember is that exec() doesn't return the matches in one big array—it keeps returning matches until it runs out, in which case it returns null.

另一个需要记住的问题是,exec()不会在一个大数组中返回匹配项——它会一直返回匹配,直到它耗尽为止,在这种情况下它返回null。

So, for example, you could do something like this:

例如,你可以这样做:

var pattern = /t(e)(s)t/g;  // Alternatively, "new RegExp('t(e)(s)t', 'g');"
var match;    

while (match = pattern.exec(text)) {
    // Do something with the match (["test", "e", "s"]) here...
}

Another thing to note is that RegExp.prototype.exec() and RegExp.prototype.test() execute the regular expression on the provided string and return the first result. Every sequential call will step through the result set updating RegExp.prototype.lastIndex based on the current position in the string.

需要注意的另一件事是RegExp.prototype.exec()和RegExp.prototype.test()在提供的字符串上执行正则表达式并返回第一个结果。每个顺序调用都将逐步执行结果集更新RegExp.prototype。基于字符串中当前位置的lastIndex。

Here's an example: // remember there are 4 matches in the example and pattern. lastIndex starts at 0

这里有一个例子://记住示例和模式中有4个匹配项。lastIndex从0开始

pattern.test(text); // pattern.lastIndex = 4
pattern.test(text); // pattern.lastIndex = 9
pattern.exec(text); // pattern.lastIndex = 14
pattern.exec(text); // pattern.lastIndex = 19

// if we were to call pattern.exec(text) again it would return null and reset the pattern.lastIndex to 0
while (var match = pattern.exec(text)) {
    // never gets run because we already traversed the string
    console.log(match);
}

pattern.test(text); // pattern.lastIndex = 4
pattern.test(text); // pattern.lastIndex = 9

// however we can reset the lastIndex and it will give us the ability to traverse the string from the start again or any specific position in the string
pattern.lastIndex = 0;

while (var match = pattern.exec(text)) {
    // outputs all matches
    console.log(match);
}

You can find information on how to use RegExp objects on the MDN (specifically, here's the documentation for the exec() function).

您可以找到关于如何在MDN上使用RegExp对象的信息(具体来说,这里是exec()函数的文档)。

#1


91  

Using String's match() function won't return captured groups if the global modifier is set, as you found out.

如果设置了全局修饰符,那么使用String的match()函数将不会返回捕获的组,正如您所发现的那样。

In this case, you would want to use a RegExp object and call its exec() function. String's match() is almost identical to RegExp's exec() function…except in cases like these. If the global modifier is set, the normal match() function won't return captured groups, while RegExp's exec() function will. (Noted here, among other places.)

在本例中,您希望使用RegExp对象并调用它的exec()函数。String's match()几乎与RegExp的exec()函数相同……但在这种情况下除外。如果设置了全局修饰符,那么普通的match()函数不会返回捕获的组,而RegExp的exec()函数会返回。(这里有提到,还有其他地方。)

Another catch to remember is that exec() doesn't return the matches in one big array—it keeps returning matches until it runs out, in which case it returns null.

另一个需要记住的问题是,exec()不会在一个大数组中返回匹配项——它会一直返回匹配,直到它耗尽为止,在这种情况下它返回null。

So, for example, you could do something like this:

例如,你可以这样做:

var pattern = /t(e)(s)t/g;  // Alternatively, "new RegExp('t(e)(s)t', 'g');"
var match;    

while (match = pattern.exec(text)) {
    // Do something with the match (["test", "e", "s"]) here...
}

Another thing to note is that RegExp.prototype.exec() and RegExp.prototype.test() execute the regular expression on the provided string and return the first result. Every sequential call will step through the result set updating RegExp.prototype.lastIndex based on the current position in the string.

需要注意的另一件事是RegExp.prototype.exec()和RegExp.prototype.test()在提供的字符串上执行正则表达式并返回第一个结果。每个顺序调用都将逐步执行结果集更新RegExp.prototype。基于字符串中当前位置的lastIndex。

Here's an example: // remember there are 4 matches in the example and pattern. lastIndex starts at 0

这里有一个例子://记住示例和模式中有4个匹配项。lastIndex从0开始

pattern.test(text); // pattern.lastIndex = 4
pattern.test(text); // pattern.lastIndex = 9
pattern.exec(text); // pattern.lastIndex = 14
pattern.exec(text); // pattern.lastIndex = 19

// if we were to call pattern.exec(text) again it would return null and reset the pattern.lastIndex to 0
while (var match = pattern.exec(text)) {
    // never gets run because we already traversed the string
    console.log(match);
}

pattern.test(text); // pattern.lastIndex = 4
pattern.test(text); // pattern.lastIndex = 9

// however we can reset the lastIndex and it will give us the ability to traverse the string from the start again or any specific position in the string
pattern.lastIndex = 0;

while (var match = pattern.exec(text)) {
    // outputs all matches
    console.log(match);
}

You can find information on how to use RegExp objects on the MDN (specifically, here's the documentation for the exec() function).

您可以找到关于如何在MDN上使用RegExp对象的信息(具体来说,这里是exec()函数的文档)。