正则表达式懒惰匹配可能空字符串

时间:2013-07-09 08:43:10

标签: ruby regex

我想在A=[和第一封]之间得到任何内容:

> str = "Hello A=[apple] B=[boy] World"
> str.match(/A=\[(.+?)\]/)[1]
 => "apple" 

到目前为止一切顺利。

然而,对于A=[]

> str = "Hello A=[] B=[boy] World"
> str.match(/A=\[(.+?)\]/)[1]
 => "] B=[boy" 

如何获取空字符串"",而不是"] B=[boy"

2 个答案:

答案 0 :(得分:4)

使用.*?而不是.+?。前者匹配零个或多个字符,而后者匹配一个或多个字符。

"Hello A=[] B=[boy] World".match(/A*=*\[(.*?)\]/)[1] # => ""

答案 1 :(得分:3)

我会用:

str = "Hello A=[apple] B=[boy] World"
str[/A=\[(.*?)\]/, 1] # => "apple"
str = "Hello A=[] B=[boy] World"
str[/A=\[(.*?)\]/, 1] # => ""

我不确定你为什么使用A*=*,因为它意味着“零或更多'A'后跟零或更多'='”并且基本上没有做任何有用的事情,事实上,实际上打开了一个洞,以返回不良结果。请参阅下面编辑中的其他信息。

以下是相同主题的变体。所有内容都记录在RegexpString.[]文档中:

str = "Hello A=[apple] B=[boy] World"
str[/A=\[(.*?)\]/, 1] # => "apple"

/A=\[(.*?)\]/ =~ str 
$1 # => "apple"

str =~ /A=\[(.*?)\]/
$1 # => "apple"

/A=\[(?<in_brackets>.*?)\]/ =~ str
in_brackets # => "apple"

str = "Hello A=[] B=[boy] World"
str[/A=\[(.*?)\]/, 1] # => ""

/A=\[(.*?)\]/ =~ str 
$1 # => ""

/A=\[(?<in_brackets>.*?)\]/ =~ str 
in_brackets # => ""

   = 旨在匹配等号之前或之后的可能空格字符,例如str =“你好A = [] B = [男孩]世界”

好吧,*=*不是你应该怎么做的。你需要告诉正则表达式引擎什么是可选的:

/A *= */

是正确的,如:

/A ?= ?/

以下是一些测试,向您展示正在发生的事情:

str = "Hello [foo] A = [apple] B=[boy] World"
str[/A*=*\[(.*?)\]/, 1] # => "foo"
str[/A *=*\[(.*?)\]/, 1] # => nil
str[/A *= *\[(.*?)\]/, 1] # => "apple"
str[/A ?= ?\[(.*?)\]/, 1] # => "apple"

请注意,您的模式/A*=*/允许引擎匹配[foo],而不是A = [apple]。这是因为您告诉它不匹配任何A=作为选项,这会打开抓住[foo]的漏洞。只要您的输入正好是两个选项,在括号内没有前置值就可以安全。如果您有输入,那么结果将是错误的。


  

str[/A.*=.*\[(.*?)\]/,1]?

都能跟得上:

str = "Hello A=[apple] B=[boy] World"
str[/A.*=.*\[(.*?)\]/,1] # => "boy"

我建议您通过Rubular探索如何使用正则表达式。这是a link showing the above example以及它失败的原因。