使用切片!在变量上正在修改填充变量的节点属性

Posted

技术标签:

【中文标题】使用切片!在变量上正在修改填充变量的节点属性【英文标题】:Using slice! on a variable is modifying the node attribute that populated the variable 【发布时间】:2018-01-20 09:25:47 【问题描述】:

在 OpsWorks Stacks 中,我使用自定义 JSON 字段设置了层属性:


  "layer_apps" : [
    "app_manager"
  ]

属性的app_ 部分是工作流所必需的。有时,我需要暂时删除食谱中的app_ 部分。为此,我使用slice!:

node['layer_apps'].each do |app_name|

  install_certs_app_name = app_name
  install_certs_app_name.slice!('app_') # 'app_manager' => 'manager'
  # snip
end

但是,一旦完成此操作,即使 app_name 没有被直接修改,每个 node['layer_apps'] 属性也会被分割,这会延续到后续的说明书并导致失败。我预期的行为是slice! 会修改app_name,而不是当前的node['layer_apps'] 属性。认为 app_name 是属性的链接而不是它自己的变量,我尝试将其值分配给单独的变量(install_certs_app_name 和其他食谱中的类似),但行为仍然存在。

这是 Ruby/Chef 中的预期行为吗?有没有更好的方法从属性中排除 app_ 前缀?

【问题讨论】:

【参考方案1】:

app_name正在被直接修改。这就是在方法后面加上 ! 的原因...这样您就知道该方法会改变对象。

app_nameinstall_certs_app_name 引用同一个对象。

请注意,sliceslice! 都返回“app_”,但 bang 对象通过删除切片文本来改变调用者。

如果你这样做了

结果 = install_certs_app_name.slice!('app_') 结果 ==> 应用程序_ 放 install_certs_app_name --> 经理

尝试(代替)

  install_certs_app_name = app_name.dup
  install_certs_app_name.slice!('app_')

所以你有两个独立的对象。

或者,

  install_certs_app_name = app_name.sub('app_', '')

【讨论】:

感谢@SteveTurczyn 的建议!我过去确实尝试过install_certs_app_name = app_name.slice('app_'),但奇怪的是,ruby 似乎返回了被删除的字符串部分,而不是结果字符串。不过,我之前没见过.dup,所以我会试一试。 是的,我的头在云端。sliceslice! 总是返回切片文本,所以 string = 'abc' ; result = string.slice('a')string = 'abc'; result = string.slice!('a') 在这两种情况下 result 都会有“a”但在第二个示例中,string 中的对象被修改了。【参考方案2】:

如果你想要一个变量切片,你需要的是非破坏性版本:

str.slice 而不是str.slice!

这些通常被称为 Bang 方法,并在适当的位置替换变量。 下面是.downcase 方法的示例。这与.slice 的原理相同。

编辑: 但是,由于 .slice 返回已被剪切的部分,您可以像删除 app_-part .sub 一样

"app_manager".sub("app_",'') #=> "manager"

http://ruby-for-beginners.rubymonstas.org/objects/bangs.html https://ruby-doc.org/core-2.2.0/String.html#method-i-slice

【讨论】:

谢谢!我确实尝试了非破坏性方法,但 slice 似乎特别返回了被删除的字符串部分,而不是剩余的字符串。有没有合适的方法让非破坏性切片返回结果字符串? 哦,对了,让我用另一个选项更新我的答案。 确实如此!史蒂夫的答案得到了复选标记,因为我第一次尝试了他的答案,它适用于我的目的,但你的答案似乎更优雅。更改已接受的答案是一种失礼吗? 无需更改 - 我不是完全为了名誉而来 ;) 而且由于他的效果也很好,这很酷,尽管复制一个字符串来分割原件似乎有点奇怪。 “如果你想要一个变量切片”——你不能切片一个变量。变量在 Ruby 中不是对象,您只能在对象上调用方法。您可以对变量做两件事,切片不是其中之一:分配变量和取消引用变量。 “这些通常被称为 Bang 方法,并在适当的位置替换变量。” – Bang-methods 仅仅意味着有一对执行类似操作的方法,但一个比另一个更令人惊讶。它确实就地替换变量。它改变了…所引用的对象【参考方案3】:

当您将app_name 分配给install_certs_app_name 时,您仍然引用同一个对象。为了创建新对象,您可以这样做:

install_certs_app_name = app_name.dup

创建具有相同值的新对象。并且以这种方式对install_certs_app_name 进行切片不会影响app_name

【讨论】:

以上是关于使用切片!在变量上正在修改填充变量的节点属性的主要内容,如果未能解决你的问题,请参考以下文章

节点无法读取 AWS Beanstalk 中的环境变量

为节点设置环境变量以检索

Dataframe.toPandas 总是在驱动节点还是工作节点上?

jQuery - 基于变量参数查找xml子项

element-ui的el-popover挂载问题

pythonnetworkx节点名称显示不全