【问题标题】:Select a block of YAML with regex使用正则表达式选择一个 YAML 块
【发布时间】:2011-10-01 14:36:04
【问题描述】:

我有一个很大的 YAML 文件,我想使用正则表达式选择整个节点。例如:

Node1:
  Child:
    GrandChild: foo
Node2:
  AnotherChild:
    AnotherGrandChild: bar
Node3:
  LastChild:
    LastGrandChild: foo

如何使用正则表达式选择上例中的所有Node2,并返回:

Node2:
  AnotherChild:
    AnotherGrandChild: bar

【问题讨论】:

  • 假设所有节点名称都是完全任意的。实际上,我没有您在上面看到的一致模式。节点名称可以是任何名称,并且可以有不定数量的子、孙等。

标签: php regex yaml


【解决方案1】:

由于该节点中的其他所有内容都是缩进的(如果我理解 YAML 正确的话),这至少在您的示例字符串中有效:

$mask = '~(^%s:\n(?:^[ ].*\n?)*$)~m';
$pattern = sprintf($mask, 'Node2');
$r = preg_match($pattern, $yaml, $matches);
$node = reset($matches);

至少在我的电脑上。想做一个键盘演示,但它给出了错误。将检查正则表达式。

完整的:

$yaml = <<<EOD
Node1:
  Child:
    GrandChild: foo
Node2:
  AnotherChild:
    AnotherGrandChild: bar
Node3:
  LastChild:
    LastGrandChild: foo
EOD;

$mask = '~
(                     # start matching group
  ^                   # a node start always at the beginning of a line 
  %s:                 # placeholder for sprintf for the nodname + :
  $                   # end of line for the nodename              
  \n
  (?:                 # non-matching group to hold all subsequent, indented lines
    ^                 # beginning of sublines
    (?:[ ]{2})+       # indentation is required, always a muliple of two spaces, non matching group
    .*\n?             # match anything else on that subsequent line, optionally the newline character
  )*                  # 0 or more subsequent, indented lines
)$                    # this ends a line, to not take over the newline of the last subsequent line (see \n? above).

# the following are modifiers:
# m - pcre multiline modifier (in php same as in perl)
# x - to allow spaces and the comments all over here ;)
~mx
';
$pattern = sprintf($mask, 'Node2');
$r = preg_match($pattern, $yaml, $matches);
$node = reset($matches);

var_dump($node);

【讨论】:

  • 哇,看起来很棒。没有用,但我认为它有潜力。缩进是两个空格的倍数——没有制表符..
  • 只是好奇..你介意帮我看看吗?我从未见过如此高级的正则表达式,我很好奇你是如何解决它的。
  • @aaron:我在每个缩进处放了两个空格并添加了一些注释。希望对您有所帮助。
  • 谢谢。那太棒了。从来不知道什么是“非匹配组”。我有最后一个问题。看起来模式有点太贪心了。如果两个节点之间的换行符不包含字符,仅包含空格,则它会将其包含为同一节点的一部分。只有当我有一个空行时,它才会在正确的位置终止匹配。我试过了,但它返回空:'~(^ %s:$\n(^([ ]{2})+[^\s]*\n?)*)$~m'有什么想法吗?
  • 从你给出的规范来看,即使是只包含空格的空行 is 也是节点的一部分。
【解决方案2】:

您可能想要使用像 php-yaml 这样的库。

【讨论】:

  • 谢谢。我正在使用它,或者类似的东西。但我真的需要一些东西来为此编辑 YAML 文本。我对解析它并不感兴趣,而是对查找和替换 YAML 的特定块感兴趣。
猜你喜欢
  • 2022-12-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-18
  • 1970-01-01
  • 2019-10-22
  • 2017-12-10
相关资源
最近更新 更多