OpsWorks Ruby 为有效的正则表达式测试返回 nil
OpsWorks Ruby returning nil for valid regex test
在 OpsWorks 中,我正在尝试测试给定节点的主机名上的数字后缀,如果它不是 1,则提取该数字。如果数字不是 1,我将此正则表达式用于匹配号码:
/([\d]+)$/
运行 反对遵循此模式的节点命名方案:
- 节点 1
- 节点2
- node3
- 节点(n...)
我已经使用 Rubular 验证了这项工作:http://rubular.com/r/Ei0kqjaxQn
但是,当我 运行 针对 OpsWorks 实例时,此匹配 returns nil,无论主机名末尾的数字是多少。 OpsWorks 代理版本是撰写本文时的最新版本 (4023),使用的是 Chef 12.13.37。
这是尝试使用匹配数字的食谱中的代码:
short_app_name.to_s + node['hostname'][/([\d]+)$/, 1].to_s + '.' + app['domains'].first
运行 失败,类型错误 no implicit conversion of nil into String
。但是,在检查节点的数字后缀时,针对 属性 的正则表达式搜索在配方的早期工作。我应该使用其他方法来提取节点的后缀吗?
编辑:app['domains'].first
已填充。如果用 domain.com
.
换出,该行仍然会失败并出现相同类型的错误
从cookbook代码和报错信息来看,问题可能是app['domains']
在运行期间是一个空数组。所以你可能想验证它的值是否正确。
当我复制您的正则表达式并将其粘贴到我的终端中进行测试时,在正则表达式末尾的美元符号后面有一个软连字符,删除它可以正常工作:
即使我从我的终端复制它,网站也没有显示它,但屏幕截图显示了问题:
第二行('irb(main):002:0')是我copy/pasted从你的食谱代码中得到的,字符是"\xc2\xad"
您的错误与正则表达式无关。
问题是当您尝试将现有的 String
与
连接起来时
app['domains'].first
这是唯一会引发此错误的地方,因为即使您的 String#slice
返回 nil
您正在调用 to_s
所以它是空的 String
但是 String
+ nil
如果 app['domains'].first
是 nil
的情况将引发此错误。
细分
#short_app_name can be nil because of explicit #to_s
short_app_name.to_s
####
# assuming node is a Hash
# node must have 'hostname' key
# or NoMethodError: undefined method `[]' for nil:NilClass wil be raised
# node['hostname'][/([\d]+)$/, 1] can be nil because of explicit #to_s
node['hostname'][/([\d]+)$/, 1].to_s
#####
# assuming app is a Hash
# app must contain 'domains' key and the value must respond to first
# and the first value must be a String or be implicitly coercible (#to_str) or it will fail with
# TypeError: no implicit conversion of ClassName into String
# could explicitly coerce (#to_s) like you do previously
app['domains'].first
示例:
node = {"hostname" => 'nodable'}
app = {"domains" => []}
node['hostname'][/([\d]+)$/, 1]
#=> nil
node['hostname'][/([\d]+)$/, 1].to_s
#=> ""
app["domains"].first
#=> nil
node['hostname'][/([\d]+)$/, 1].to_s + '.' + app["domains"].first
#=> TypeError: no implicit conversion of nil into String
node = {"hostname" => 'node2'}
app = {"domains" => ['here.com']}
node['hostname'][/([\d]+)$/, 1].to_s + '.' + app["domains"].first
#=> "2.here.com"
在 OpsWorks 中,我正在尝试测试给定节点的主机名上的数字后缀,如果它不是 1,则提取该数字。如果数字不是 1,我将此正则表达式用于匹配号码:
/([\d]+)$/
运行 反对遵循此模式的节点命名方案:
- 节点 1
- 节点2
- node3
- 节点(n...)
我已经使用 Rubular 验证了这项工作:http://rubular.com/r/Ei0kqjaxQn
但是,当我 运行 针对 OpsWorks 实例时,此匹配 returns nil,无论主机名末尾的数字是多少。 OpsWorks 代理版本是撰写本文时的最新版本 (4023),使用的是 Chef 12.13.37。
这是尝试使用匹配数字的食谱中的代码:
short_app_name.to_s + node['hostname'][/([\d]+)$/, 1].to_s + '.' + app['domains'].first
运行 失败,类型错误 no implicit conversion of nil into String
。但是,在检查节点的数字后缀时,针对 属性 的正则表达式搜索在配方的早期工作。我应该使用其他方法来提取节点的后缀吗?
编辑:app['domains'].first
已填充。如果用 domain.com
.
从cookbook代码和报错信息来看,问题可能是app['domains']
在运行期间是一个空数组。所以你可能想验证它的值是否正确。
当我复制您的正则表达式并将其粘贴到我的终端中进行测试时,在正则表达式末尾的美元符号后面有一个软连字符,删除它可以正常工作:
即使我从我的终端复制它,网站也没有显示它,但屏幕截图显示了问题:
第二行('irb(main):002:0')是我copy/pasted从你的食谱代码中得到的,字符是"\xc2\xad"
您的错误与正则表达式无关。
问题是当您尝试将现有的 String
与
app['domains'].first
这是唯一会引发此错误的地方,因为即使您的 String#slice
返回 nil
您正在调用 to_s
所以它是空的 String
但是 String
+ nil
如果 app['domains'].first
是 nil
的情况将引发此错误。
细分
#short_app_name can be nil because of explicit #to_s
short_app_name.to_s
####
# assuming node is a Hash
# node must have 'hostname' key
# or NoMethodError: undefined method `[]' for nil:NilClass wil be raised
# node['hostname'][/([\d]+)$/, 1] can be nil because of explicit #to_s
node['hostname'][/([\d]+)$/, 1].to_s
#####
# assuming app is a Hash
# app must contain 'domains' key and the value must respond to first
# and the first value must be a String or be implicitly coercible (#to_str) or it will fail with
# TypeError: no implicit conversion of ClassName into String
# could explicitly coerce (#to_s) like you do previously
app['domains'].first
示例:
node = {"hostname" => 'nodable'}
app = {"domains" => []}
node['hostname'][/([\d]+)$/, 1]
#=> nil
node['hostname'][/([\d]+)$/, 1].to_s
#=> ""
app["domains"].first
#=> nil
node['hostname'][/([\d]+)$/, 1].to_s + '.' + app["domains"].first
#=> TypeError: no implicit conversion of nil into String
node = {"hostname" => 'node2'}
app = {"domains" => ['here.com']}
node['hostname'][/([\d]+)$/, 1].to_s + '.' + app["domains"].first
#=> "2.here.com"