【问题标题】:How can I capture an optional group in regex?如何在正则表达式中捕获可选组?
【发布时间】:2020-10-03 19:56:38
【问题描述】:

我有一个如下的正则表达式:

    const verseRegex = /(?<chapterBegin>[^\\d+$]*):(?<verseBegin>[^\\d+$]*)-((?<chapterEnd>[^\\d+$]*):)?(?<verseEnd>[^\\d+$]*)/g;

我希望正则表达式能够匹配以下两个字符串:

  • 4:1-13
  • 4:1-5:20

但是正则表达式只能匹配第一个字符串并正确分组:

console.log(verseRegex.exec('4:1-13');

[
  '4:1-13',
  '4',
  '1',
  undefined,
  undefined,
  '13',
  index: 0,
  input: '4:1-13',
  groups: [Object: null prototype] {
    chapterBegin: '4',
    verseBegin: '1',
    chapterEnd: undefined,
    verseEnd: '13'
  }
]

返回第二个字符串null。 我对上述行为没有任何解释。当我删除可选组并将我的正则表达式重写为:

const verseRegex = /(?<chapterBegin>[^\\d+$]*):(?<verseBegin>[^\\d+$]*)-(?<chapterEnd>[^\\d+$]*):(?<verseEnd>[^\\d+$]*)/g;

现在第二个字符串按预期匹配和分组,第一个字符串失败,因为chapterEnd 组不再是可选的。 如何重写我的正则表达式以匹配和分组两个字符串?

【问题讨论】:

  • 如果有任何帮助,以下在 Python 中工作 r'(?P&lt;chapterBegin&gt;\d+):(?P&lt;verseBegin&gt;\d+)-((?P&lt;chapterEnd&gt;\d+):)?(?P&lt;verseEnd&gt;\d+)' 虽然我不能轻松地直接使用 Javascript 检查自己,但可能值得看看等效的东西(可能是 /(?&lt;chapterBegin&gt;\\d+):(?&lt;verseBegin&gt;\\d+)-((?&lt;chapterEnd&gt;\\d+):)?(?&lt;verseEnd&gt;\\d+)/)是否可以工作。
  • @alaniwi javascript 版本不起作用。我已经尝试过 python 版本,但它可以工作,但我不知道如何在 javascript 中编写等效的版本。

标签: javascript regex string parsing regex-group


【解决方案1】:

注意[^\\d+$]* 模式匹配除\d+$ 字符之外的任何字符。你一定是想匹配一个或多个数字块,所以你需要\d+

你可以使用

/^(?<chapterBegin>\d+):(?<verseBegin>\d+)-(?:(?<chapterEnd>\d+):)?(?<verseEnd>\d+)$/

或者,没有命名的捕获组(例如,对于 IE):

/^(\d+):(\d+)-(?:(\d+):)?(\d+)$/

regex demo

查看 JavaScript 演示:

const strs = ['4:1-13','4:1-5:20'];
const rx = /^(?<chapterBegin>\d+):(?<verseBegin>\d+)-(?:(?<chapterEnd>\d+):)?(?<verseEnd>\d+)$/;
for (let s of strs) {
  const results = rx.exec(s);
  console.log(s, results.groups);
}

输出:

4:1-13 {
  "chapterBegin": "4",
  "verseBegin": "1",
  "chapterEnd": undefined,
  "verseEnd": "13"
}
4:1-5:20 {
  "chapterBegin": "4",
  "verseBegin": "1",
  "chapterEnd": "5",
  "verseEnd": "20"
}

旧浏览器演示:

var strs = ['4:1-13','4:1-5:20'];
var rx = /^(\d+):(\d+)-(?:(\d+):)?(\d+)$/;
for (var i=0; i<strs.length; i++) {
  var results = rx.exec(strs[i]);
  console.log(strs[i], results);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-06
    相关资源
    最近更新 更多