我希望以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
的答案。
答案 0 :(得分:5)
第二个正则表达式有问题:
^(IN:[AE][0-9]{7}Q)|([AE][0-9]{7})$
|
的优先级低于连接,因此正则表达式将被解析为:
^(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})
要解决此问题,只需使用非捕获组:
^(?:(IN:[AE][0-9]{7}Q)|([AE][0-9]{7}))$
确保输入字符串与任何格式匹配,而不仅仅是以某种格式开头或结尾(这显然不正确)。
关于缩短正则表达式,如果您愿意,可以将[0-9]
替换为\d
,但它可以正常使用。
我认为在Ruby的默认支持级别内没有任何其他方法可以缩短正则表达式。
只是为了您的信息,在Perl / PCRE中,您可以使用 子例程调用 来缩短它:
^(?:([AE][0-9]{7})|(IN:(?1)Q))$
(?1)
是指第一个捕获组定义的模式,即[AE][0-9]{7}
。正则表达式实际上是相同的,只是看起来更短。输入IN:E0123463Q
的{{3}}显示第2组捕获的整个文本(并且没有为第1组捕获的文本)。
在Ruby中,存在This demo 子表达式调用 ,语法略有不同。 Ruby使用\g<name>
或\g<number>
来引用我们想要重用其模式的捕获组:
^(?:([AE][0-9]{7})|(IN:\g<1>Q))$
Ruby 1.9.7下的similar concept,对于输入IN:E0123463Q
,返回E0123463
作为第1组匹配,IN:E0123463Q
作为第2组匹配。
Ruby的(1.9.7)实现似乎记录了组1的捕获文本,即使组1没有直接参与匹配。在PCRE中,子程序调用不会捕获文本。
还有 条件正则表达式 ,可让您检查某个捕获组是否与某些内容匹配。您可以查看test case here on rubular以获取更多信息。
答案 1 :(得分:3)
如果您使用的是Ruby 2.0,则可以使用if-then-else conditional match(在Ruby文档中未记录,但确实存在):
/^(IN:)?[AE][0-9]{7}(?(1)Q|)$/
条件部分为(?(1)Q|)
,表示如果组号1匹配,则匹配Q
,否则不匹配。由于第1组是(IN:)
,因此可以实现您的目标。