我想在格式字符串相匹配A0123456,E0123456或者IN:A0123456Q等我最初用这种正则表达式
^(IN:)?[AE][0-9]{7}Q?$
但它IN:E012346没有Q在最后匹配.所以我创建了这个正则表达式
(^IN:[AE][0-9]{7}Q$)|(^[AE][0-9]{7}$)
有没有办法缩短这个正则表达式,以便它需要两者IN:,Q如果它们存在,但如果两者都不存在则不需要?
编辑:正则表达式将在Ruby中使用.
编辑2:我改变了正则表达式,以反映我匹配错误的字符串,因为它仍然匹配IN:A0123456.
编辑3:下面的两个答案都是有效的,但由于我正在使用Ruby 2.0并且更喜欢正则表达式,我可以使用以防我改变我的应用程序并且不想使用子表达式调用的Ruby风格,我选择接受它matt的答案.
第二个正则表达式有问题:
^(IN:[AE][0-9]{7}Q)|([AE][0-9]{7})$
Run Code Online (Sandbox Code Playgroud)
将|具有比串联的优先级低,所以正则表达式会被解析为:
^(IN:[AE][0-9]{7}Q) # Starts with (IN:[AE][0-9]{7}Q)
| # OR
([AE][0-9]{7})$ # Ends with ([AE][0-9]{7})
Run Code Online (Sandbox Code Playgroud)
要解决此问题,只需使用非捕获组:
^(?:(IN:[AE][0-9]{7}Q)|([AE][0-9]{7}))$
Run Code Online (Sandbox Code Playgroud)
它确保输入字符串匹配任一格式,而不仅仅是以某种格式开始或结束(这显然是不正确的).
关于缩短正则表达式,则可以替换[0-9]使用\d,如果你想,但它是好的,因为它是.
我认为在Ruby的默认支持级别内没有任何其他方法可以缩短正则表达式.
只是为了您的信息,在Perl/PCRE中,您可以通过子程序调用缩短它:
^(?:([AE][0-9]{7})|(IN:(?1)Q))$
Run Code Online (Sandbox Code Playgroud)
(?1)指第一捕获组定义的模式,即[AE][0-9]{7}.正则表达式实际上是相同的,只是看起来更短.这个带有输入的演示IN:E0123463Q显示了第2组捕获的整个文本(并且没有为第1组捕获的文本).
在Ruby中,存在类似的概念 子表达式调用,语法略有不同.Ruby使用\g<name>或\g<number>引用我们想要重用其模式的捕获组:
^(?:([AE][0-9]{7})|(IN:\g<1>Q))$
Run Code Online (Sandbox Code Playgroud)
在这里rubular测试用例红宝石1.9.7下,对于输入IN:E0123463Q,返回E0123463作为匹配组1和IN:E0123463Q作为匹配组2.
Ruby的(1.9.7)实现似乎记录了组1的捕获文本,即使组1没有直接参与匹配.在PCRE中,子程序调用不捕获文本.
还有条件正则表达式,允许您检查某个捕获组是否匹配.您可以查看matt的答案以获取更多信息.
如果您使用的是 Ruby 2.0,则可以使用if-then-else 条件匹配(Ruby 文档中未记录,但确实存在):
/^(IN:)?[AE][0-9]{7}(?(1)Q|)$/
Run Code Online (Sandbox Code Playgroud)
条件部分(?(1)Q|)表示如果组号 1 匹配,则匹配Q,否则不匹配。由于组号 1 是(IN:),这实现了您想要的。
| 归档时间: |
|
| 查看次数: |
494 次 |
| 最近记录: |