我有:
"here is BN1234 and other BN456[these are things] and other".scan(/BN([a-zA-Z0-9\-_.]+)/)
=>[["1234"], ["456"]]
我想添加一个可选片段,它可以捕获结果后面的可选括号分隔字符串。捕获可以包含任何UTF-8字符,直到终止端括号。理想的情况是:
"here is BN1234 and other BN456[these are things]".scan(???)
=>[["1234"], ["456[these are things]"]]
谷歌搜索,我尝试过:
"here is BN1234 and other BN456[these are other things]".scan(/BN([a-zA-Z0-9\-_.]+)([.+])?/)
=> [["1234", nil], ["456", nil]] # <- NO
和
"here is BN1234 and other BN456[these are other things]".scan(/BN([a-zA-Z0-9\-_.]+\[\d+\])?/)
=> [[nil], [nil]]
获得所需结果的可选模式是什么?
答案 0 :(得分:1)
"here is BN1234 and other BN456[these are things] and other".scan(/BN([a-zA-Z0-9\-_.]+(?:\[[^\]]+\])?)/)
# => [["1234"], ["456[these are things]"]]
您可以查看here
答案 1 :(得分:1)
如果您从像Rubular这样的网站开始,您会发现创建/调试模式要容易得多。
这是一个起点:http://rubular.com/r/G93iPo0j5C
/BN([\w.-]+)(\[[^\]]+\])?/
将其应用于scan
:
'here is BN1234 and other BN456[these are things]'.scan(/BN([\w.-]+)(\[[^\]]+\])?/)
# => [["1234", nil], ["456", "[these are things]"]]
稍微调整以调整捕获结果:
'here is BN1234 and other BN456[these are things]'.scan(/BN([\w.-]+(?:\[[^\]]+\])?)/)
# => [["1234"], ["456[these are things]"]]
展平结果以摆脱嵌入的子阵列:
'here is BN1234 and other BN456[these are things]'.scan(/BN([\w.-]+(?:\[[^\]]+\])?)/).flatten
# => ["1234", "456[these are things]"]
创建图案时,简单地开始并尽可能减少视觉噪音非常重要。而不是使用[a-zA-Z0-9\-_.]
,了解字符集的工作原理。 \d
相当于[0-9]
,因此您可以将模式缩减为[a-zA-Z\d\-_.]
。
进一步缩小\w
相当于[a-zA-Z0-9_]
,因此模式变为[\w\-.]
。
最后,-
内的[]
应该在集合的开头或结尾定义,因为它会自动转义,进一步降低视觉噪音:[\w.-]
。
我可以问内部[^]会做什么吗?
是。你可以问。让我们分解一下:你想要在方括号内捕获文本。要捕获方括号,您必须逃避前导方括号,为清楚起见,您应该避开尾随方括号。 \[[^\]]+\]
是:
\[
=文字起点&#39; [
&#39;。[^\]]
=符合文字&#39; ]
&#39;的 字符集。\]
=结束文字&#39; ]
&#39;字符。关于正则表达式模式,有一些非常重要的事情需要学习和记住。它们非常强大,但它们 NOT 是存在的每个计算/解析问题的答案。我们遇到的每个程序员,当他们了解到正则表达式时,立即尝试将它们用于所有可能的事情。这不是一个好的决定,因为编写在逻辑上漏洞的模式非常容易,通常非常糟糕。未能逃脱.
或[
,或滥用*
或+
,或遇到贪婪问题,可能会导致很难发现的错误。编写长图案只会增加打开这些洞的可能性,所以要保持它们的简短和甜蜜,测试它们,然后学习如何聚合它们以重复使用它们来创建大的洞。
Stack Exchange上一个臭名昭着的角色写了&#34; Regular Expressions: Now You Have Two Problems&#34;,这是一个很好的阅读。这本书&#34; Perl Best Practices&#34;有一个很好的章节解释了如何以及为什么使用模式以及如何以可读/可维护的方式编写模式。还有&#34; Mastering Regular Expressions&#34;这是必须参考的。你不必知道关于他们的一切,但是拥有&#34; MRE&#34;当你有疑问时,书会给你一个好看的地方。
答案 2 :(得分:1)
我会使用与其他人建议的略有不同的正则表达式
str = "here is BN1234 and other BN456[these are other things]"
str.scan(/(?:^|\s)BN(\d+(?:\[[^\]]+\])?)/i)
#=> [["1234"], ["456[these are other things]"]]
(?:...)
表示非捕获组。(?:^|\s)
要求BN
位于字符串的开头(^
)或(|
)前面至少有一个空白字符({{1} }})。\s
要求\d+
后跟至少一位数。BN
末尾的?
表示非捕获组(?:\[[^\]]+\])?
是可选的。(?:\[[^\]]+\])
和\[
是(字面意思)打开和关闭大括号。需要转义才能将它们与正则表达式组的开头和结尾区分开来。\]
匹配字符类[^\]+
中的一个或多个字符。 [^\]
表示右括号以外的所有字符都与字符类匹配。