JS正则表达式捕获所有匹配组和位置

3

说明: 我刚开始学习正则表达式,试图在javascript中学习捕获组

  1. 我使用https://regex101.com/r/COYhIc/1 进行测试
  2. 请参考附加的图像了解每个匹配项的字符位置列 https://regex101.com

目标:

  1. 我想在控制台上打印所有匹配和捕获组 (已完成)
  2. 我想打印每个匹配项的字符位置 [请参考图片] (未完成)

enter image description here

JSFIDDLE: https://jsfiddle.net/bababalcksheep/p28fmdk4/68/

JavaScript:

function parseQuery(query) {
  var isRE = query.match(/^\/(.*)\/([a-z]*)$/);
  if (isRE) {
    try {
      query = new RegExp(isRE[1], isRE[2]);
    } catch (e) {}
  }
  return query;
}
var str = $('#str').val();
var regex = parseQuery($('#reg').val());
//
var result;
var match_no = 0;
var output = '';
while ((result = regex.exec(str)) !== null) {
  match_no++;
  output += `\nMatch ${match_no}\n`;
  output += `Full Match, ${ result[0]} , Pos\n`;
  for (i = 1; i < result.length; i++) {
    output += `Group ${i}, ${ result[i]} , Pos\n`;
  }
}
console.log(output);

类似问题:https://dev59.com/a2Uo5IYBdhLWcg3wkQNq - Klesun
2个回答

1
根据RegExp.exec文档,您可以使用index属性检索它。因此,我会将这行代码添加到您的片段中,以检索完全匹配的列位置:
`${result.index}-${result.index + result[0].length}`

针对子组,JS无法检索索引,因此可以使用indexOf来实现解决方法:
const initialSubGroupIndex = str.indexOf(result[i], result.index);
`${initialSubGroupIndex}-${initialSubGroupIndex + result[i].length}`

1
但是第一组和第二组呢?我在那里遇到了问题,完全匹配是正确的,但其余的都是错误的。 - django
@django 不幸的是,js 默认不提供访问组索引的功能。在您的情况下,我会建议您在实际字符串 str 中搜索找到的组结果 result[1] 和 result[2]。可以使用类似 str.indexOf(result[1]) 的方法。 - guijob
1
str.indexOf(result[1]) 可能会产生错误的结果,因为值为 100 的第二组被重复了两次。 - django
@django 更新了我的回答! - Tushar
没有一个解决方案可以通过测试用例 str=aaaaaaaaaaaaaa,regex=/a(a*)a/g。要找到子组的索引是不可能的,只有当捕获的字符串在匹配中只出现一次时才能做到。 - nhahtdh
显示剩余4条评论

1
在你的输出字段中使用indexlastIndexexec返回一个带有索引属性的对象。
output += `Full Match, ${ result[0]} , Pos ${result.index} - ${regex.lastIndex}\n `;

关于群组的更新:

我使用了一个小逻辑来获取索引:

var m = new RegExp(result[i]);
output += `Group ${i}, ${ result[i]}, Pos ${$('#str').val().match(m).index} - ${regex.lastIndex} \n`;

function parseQuery(query) {
  var isRE = query.match(/^\/(.*)\/([a-z]*)$/);
  if (isRE) {
    try {
      query = new RegExp(isRE[1], isRE[2]);
    } catch (e) {}
  }
  return query;
}
var str = $('#str').val();
var regex = parseQuery($('#reg').val());
//
var result;
var match_no = 0;
var output = '';
while ((result = regex.exec(str)) !== null) {
  match_no++;
  output += `\nMatch ${match_no}\n`;
  output += `Full Match, ${ result[0]} , Pos ${result.index} - ${regex.lastIndex}\n `;
  for (i = 1; i < result.length; i++) {
    var m = new RegExp(result[i]);
    output += `Group ${i}, ${ result[i]}, Pos ${$('#str').val().match(m).index} - ${regex.lastIndex} \n`;
  }
}
console.log(output);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
  <div class="form-group">
    <label for="str">String:</label>
    <input type="text" class="form-control" id="str" value="source=100, delta=2, source=2121, delta=5">
  </div>
  <div class="form-group">
    <label for="regex">Regex:</label>
    <input type="text" class="form-control" id="reg" value="/(source=(\d+))/g">
  </div>
  <div id="result">

  </div>
</div>

篮子


关于分组怎么样?对于完全匹配来说没问题,但对于第二个分组不行。 - django
使用fiddle https://jsfiddle.net/bababalcksheep/p28fmdk4/68/,我已更新以确保与https://regex101.com/r/COYhIc/1完全匹配,并查看组2的差异。 - django
@django 更新了答案! - Tushar
FYI我使用了旧的js fiddle,但它运行良好。 :) - Tushar
没有任何一种解决方案能够通过测试用例 str = aaaaaaaaaaaaaa,regex = /a(a*)a/g。找到子组的索引是不可能的 - 只有在匹配中捕获的字符串仅出现一次时才能这样做。 - nhahtdh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接