Javascript Regex exec 只返回第一个匹配项

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5283071/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 16:28:21  来源:igfitidea点击:

Regex exec only returning first match

javascriptregex

提问by poke

I am trying to implement the following regex search found on golfscript syntax page.

我正在尝试实现在Golfscript 语法页面上找到的以下正则表达式搜索。

var ptrn = /[a-zA-Z_][a-zA-Z0-9_]*|'(?:\.|[^'])*'?|"(?:\.|[^"])*"?|-?[0-9]+|#[^\n\r]*|./mg;
input = ptrn.exec(input);

Input is only ever the first match of the regexp. for example: "hello" "world"should return ["hello", "world"]but it only returns ["hello"].

输入只是正则表达式的第一个匹配项。例如: "hello" "world"应该返回["hello", "world"]但它只返回["hello"].

回答by poke

RegExp.execis only able to return a single match result at once.

RegExp.exec 一次只能返回一个匹配结果。

In order to retrieve multiple matches you need to run execon the expression object multiple times. For example, using a simple while loop:

为了检索多个匹配项,您需要exec多次在表达式对象上运行。例如,使用一个简单的 while 循环:

var ptrn = /[a-zA-Z_][a-zA-Z0-9_]*|'(?:\.|[^'])*'?|"(?:\.|[^"])*"?|-?[0-9]+|#[^\n\r]*|./mg;

var match;
while ((match = ptrn.exec(input)) != null) {
    console.log(match);
}

This will log all matches to the console.

这会将所有匹配记录到控制台。

Note that in order to make this work, you need to make sure that the regular expression has the g(global) flag. This flag makes sure that after certain methods are executed on the expression, the lastIndexpropertyis updated, so further calls will start afterthe previous result.

请注意,为了完成这项工作,您需要确保正则表达式具有g(全局)标志。此标志确保在表达式上执行某些方法后,更新lastIndex属性,因此将上一个结果之后开始进一步调用。

回答by Eadel

It is possible to call matchmethod on the string in order to retrieve the whole collection of matches:

可以match在字符串上调用方法以检索整个匹配集合:

var ptrn = /[a-zA-Z_][a-zA-Z0-9_]*|'(?:\.|[^'])*'?|"(?:\.|[^"])*"?|-?[0-9]+|#[^\n\r]*|./mg;
var results = "hello world".match(ptrn);

resultsare (according to the regular expression):

results是(根据正则表达式):

["hello", " ", "world"]

matchspec is here

match规格在这里

回答by Little Alien

I did not get what is meant by "hello" "world"in your question, is it user input or regex but I was told that RegExp object has a state -- its lastIndexposition that it starts the search from. It does not return all the results at once. It brings only the first match and you need to resume .execto get the rest of results starting from lastIndex position:

我不明白"hello" "world"你的问题是什么意思,它是用户输入还是正则表达式,但我被告知 RegExp 对象有一个状态——lastIndex它开始搜索的位置。它不会一次返回所有结果。它只带来第一场比赛,您需要继续.exec获得从 lastIndex 位置开始的其余结果:

const re1 = /^\s*(\w+)/mg; // find all first words in every line
const text1 = "capture discard\n me but_not_me" // two lines of text
for (let match; (match = re1.exec(text1)) !== null;) 
      console.log(match, "next search at", re1.lastIndex);

prints

印刷

["capture", "capture"] "next search at" 7
[" me", "me"] "next search at" 19

The functional JS6 way to build iterator for your results is here

为您的结果构建迭代器的功能性 JS6 方法在这里

RegExp.prototype.execAllGen = function*(input) {
    for (let match; (match = this.exec(input)) !== null;) 
      yield match;
} ; RegExp.prototype.execAll = function(input) {
  return [...this.execAllGen(input)]}

Please also note how, unlike poke, much more nicely I used matchvariable enclosed in the for-loop.

另请注意,与poke不同,我如何更好地使用-loop 中match包含的变量for

Now, you can capture your matches easily, in one line

现在,您可以在一行中轻松捕获匹配项

const matches = re1.execAll(text1)

log("captured strings:", matches.map(m=>m[1]))
log(matches.map(m=> [m[1],m.index]))
for (const match of matches) log(match[1], "found at",match.index)

which prints

哪个打印

"captured strings:" ["capture", "me"]

[["capture", 0], ["me", 16]]
"capture" "found at" 0
"me" "found at" 16