命名捕获组不适用于动态正则表达式

时间:2017-09-09 02:40:58

标签: ruby-on-rails ruby

我有一个正在动态构建的正则表达式:

permitted_keys = %w[attachment avatar banner document]

# my actual key
key = 'banner_content_type'

# g1 will be the captured grouped or nil
/(?<g1>#{permitted_keys.join('|')})_content_type/ =~ key

p "g1 #{g1.inspect}"

问题是动态构建此正则表达式我收到以下错误:

  

NameError(未定义的局部变量或方法`g1'表示......

但是,如果我静态地将值放在正则表达式中,就像这样:

/(?<g1>attachment|avatar|banner|document)_content_type/ =~ key

完全有效。

第一种方法有什么问题? TIA。

PS:

我已经在终端比较了以下内容:

/(?<g1>#{permitted_keys.join('|')})_content_type/ == 
/(?<g1>attachment|avatar|banner|document)_content_type/

...并返回true

您可以查看以下链接中的示例:

Example 1
Example 2

1 个答案:

答案 0 :(得分:2)

第一种方法的问题是在正则表达式文字中使用字符串插值会禁用局部变量的赋值。来自Regexp#=~

  

如果=~与带有命名捕获的正则表达式文字一起使用,则捕获的字符串(或nil)将分配给由捕获名称命名的局部变量。

     

......剪断......

     

此分配在Ruby解析器中实现。解析器检测到赋值的'regexp-literal = ~expression'。 正则表达式必须是没有插值的文字并放在左侧。

     

......剪断......

     

正则表达式插值#{}也会禁用赋值。

你总是可以使用Regexp#match来获取捕获,但我还是不确定是否自动分配这样的局部变量(老实说,我不知道=~会这样做):

match_data = /(?<g1>#{permitted_keys.join('|')})_content_type/.match(key)
match_data['g1']
# => "banner"

或者如果你喜欢处理全局变量:

/(?<g1>#{permitted_keys.join('|')})_content_type/ =~ key
$~['g1']
# => "banner"