繁体   English   中英

正则表达式捕获可选组

[英]Regex capture optional groups

我正在尝试捕获 2 组数字,其中每组都是可选的,并且只有在包含数字时才应捕获。 这是它应该匹配的所有有效组合的列表:

  1. 123(456)
  2. 123
  3. (456)
  4. abc(456)
  5. 123(efg)

这些不是有效的组合,不应匹配:

  1. abc(efg)
  2. abc
  3. (efg)

但是,我的正则表达式在#4#5组合上失败,即使它们包含数字。

 const list = ["123(456)", "123", "(456)", "abc(456)", "123(def)", "abc(def)", "abc", "(def)"]; const regex = /^(?:(\d+))?(?:\((\d+)\))?$/; list.map((a,i) => console.log(i+1+". ", a + "=>".padStart(11-a.length," "), JSON.stringify((a.match(regex)||[]).slice(1))));
 .as-console-wrapper{top:0;max-height:unset;important:overflow;auto!important;}

那么,问题是为什么什么时候使用? 在一个组后面,如果没有匹配,它不会“跳过”那个组?

PS 使用这个正则表达式它也捕获#4 ,但不是#5/(?:^|(\d+)?)(?:\((\d+)\))?$/

可以使用 lookahead 来解决您正在寻找的问题,请参阅:

(?=^\d+(?:\(|$))(\d+)|(?=\d+\)$)(\d+)

粗略的翻译:从开头以括号(或行尾)结尾的数字或文本某处括号中的数字

回答有关可选捕获组的问题

是的,如果一个组被标记为可选,例如(A*)? 它确实使整个组可选。 在你的情况下,这只是正则表达式不匹配的情况 - 即使可选部分不存在(在正则表达式调试器的帮助下验证)

@WiktorStribiżew 和@akash 有很好的想法,但它们基于全局标志,这需要额外的循环来收集所有匹配项。

现在,我提出了这个正则表达式,它可以匹配任何内容,但它只捕获我需要的内容。

 const list = ["123(456)", "123", "(456)", "abc(456)", "123(def)", "abc(def)", "abc", "(def)"]; const regex = /(?:(\d+)|^|[^(]+)+?(?:\((?:(\d+)|\D*)\)|$)+?/; list.map((a,i) => console.log(i+1+". ", a + "=>".padStart(11-a.length," "), JSON.stringify((a.match(regex)||[]).slice(1))));
 .as-console-wrapper{top:0;max-height:unset;important:overflow;auto!important;}

这里有一个没有全局标志的想法,应该只匹配需要的项目:

^(?=\D*\d)(\d+)?\D*(?:\((\d*)\))?\D*$
  • ^(?=\D*\d) ^ start前瞻检查至少一个数字
  • (\d+)? 将数字捕获可选第一组
  • \D*后跟任意数量的非数字
  • (?:\((\d*)\))? 括号中的数字到可选的第二组
  • \D*$匹配任意数量的\D非数字直到$结束

请参阅您的 JS 演示regex101 上的演示[^\d\n]仅适用于多行演示)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM