首页 > 解决方案 > Puppet 正则表达式(在引号之间的 var 中抓取路径)

问题描述

我有以下yaml:

role::project::conf::files:
  entry_01:
    - 'file "/var/project/some_file.txt" 5333;'
    - 'echo no;'
  entry_02:
    - 'file "/var/project/some_other_file.txt" 5334;'
    - 'echo yes;'
  entry_03:
    - 'file "/var/project/extra_file.txt" 5335;'
    - 'echo yes;'

然后我使用了以下正则表达式https://regex101.com/r/pVzseA/1来获取这些引号之间的值(正则表达式在 regex101.com 中有效)但在 Puppet 中不起作用:

each($files) | $files_itm | {
  if $files_itm[1] =~ /"([^"]*)"/ {
    #how to get only the path here in var
  }
}

更新,班级:

class role::project::conf (
  $files = [],
){
  each($files) | $files_itm | {
    if $files_itm[1] =~ /"([^"]*)"/ {
      notify { "file ${1} seen": }
    }
  }
}

标签: regexrubyyamlpuppet

解决方案


我使用了以下正则表达式 https://regex101.com/r/pVzseA/1来获取这些引号之间的值(正则表达式在 regex101.com 中有效)但在 Puppet 中不起作用:

each($files) | $files_itm | {
  if $files_itm[1] =~ /"([^"]*)"/ {
    #how to get only the path here in var
  }
}

正如我在评论中指出的,Puppet 使用了 Ruby 的正则表达式风格。这不在 Regex101 明确支持的范围之内,因此在那里工作的正则表达式不适用于 Puppet 并不是不可能的。但是, Rubular的 Ruby 风格在线正则表达式测试器显示您的特定正则表达式在 Ruby 中运行良好,包括匹配组。

您没有展示如何尝试在 Puppet 代码中获取匹配组,但Puppet 的正则表达式文档中给出了适当的过程。尤其是:

在条件语句和节点定义中,正则表达式中带有 [sic] 括号的子字符串()可用作相关代码部分内的编号变量。第一个是$1,第二个是$2,以此类推。整场比赛可作为$0. 这些不是正常变量,并且有一些特殊的行为:[...]

这也反映在条件语句的文档中

您只有一个捕获组,因此在条件语句的主体内,您可以将捕获的内容称为$1. 例如,

each($files) | $files_itm | {
  if $files_itm[1] =~ /"([^"]*)"/ {
    notify { "file ${1} seen": }
  }
}

但是请注意,捕获组变量只能在条件语句的主体内访问,并且在其条件中具有正则表达式匹配的任何嵌套条件之外。此外,如果在同一条件语句的条件中有两个或多个正则表达式匹配表达式,似乎没有记录其含义。

更新

但是问题的更新和您在评论中提出的错误消息表明您正在努力解决的问题是完全不同的。与 Hiera key 关联的值role::project::conf::fileshash,带有字符串键和数组值,而您似乎期望根据编码到类中的参数默认值的数组。当您迭代哈希并捕获单个变量中的条目时,该变量将采用双元素数组值,其中第一个(元素 0)是条目的键,第二个(元素 1)是对应的值。

因此,当问题中显示的 Hiera 数据绑定到您的$files参数时,您的表达式将$files_itm[1]计算为数组值,例如['file "/var/project/some_file.txt" 5333;', 'echo no;']. 这些不适合运算符的左手操作数=~,这就是错误消息告诉您的内容。

在这里很难说出你真正想要什么,但这至少应该避免错误(结合你的 YAML 数据):

each($files) | $itm_key, $itm_value | {
  if $itm_value[0] =~ /"([^"]*)"/ {
    notify { "file ${1} seen": }
  }
}

推荐阅读