[英]Regex capture optional groups
我正在尝试捕获 2 组数字,其中每组都是可选的,并且只有在包含数字时才应捕获。 这是它应该匹配的所有有效组合的列表:
123(456)
123
(456)
abc(456)
123(efg)
这些不是有效的组合,不应匹配:
abc(efg)
abc
(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.