Sed / Awk从Yaml删除多行直到两个空格

时间:2018-01-12 19:47:54

标签: regex bash awk sed

这个让我很难过,而且我似乎找不到其他SO问题的精确匹配。我已经非常接近,所以也许有人可以指出我失踪的东西。

我有一个名为test.yml的yaml文件,如下所示:

sites:
  qwerty:
    hosts:
      - qwerty.test
  abc:
    repo:
    hosts:
      - abc.test
    other:
  xyz:
    repo:
    hosts:
      - xyz.test
utilities:
  stuff:
    - thing
    - thing 2

我想使用bash脚本删除所有abc:block。我不能指望相同的行数。我愿意使用任何方法,只要它被广泛接受(这是一个开源项目)。理想情况下,完成后会看起来像这样:

sites:
  qwerty:
    hosts:
      - qwerty.test
  xyz:
    repo:
    hosts:
      - xyz.test
utilities:
  stuff:
    - thing
    - thing 2

现在我已经达到了这个目标:

sed -e "/  abc:/,/  \w/d" test.yml > test.tmp

但结果是:

sites:
  qwerty:
    hosts:
      - qwerty.test

我的思维过程是匹配,直到有两个空格和一个单词但我似乎匹配两个空格,当有四个并删除所有内容。如何使用Regex明确地定位两个空格和一个单词?或者有更好的方法吗?

4 个答案:

答案 0 :(得分:1)

要操作jsonyaml文件,您应该使用原生数据格式的工具。 您可以使用[ y2j ]中指出的comment。从git repo下载zip并将其解压缩到文件夹。将您的yaml文件放在前面提到的文件夹中,然后执行:

# cat test.yaml 
sites:
  qwerty:
    hosts:
      - qwerty.test
  abc:
    repo:
    hosts:
      - abc.test
    other:
  xyz:
    repo:
    hosts:
      - xyz.test
utilities:
  stuff:
    - thing
    - thing 2
# ./y2j 'del(.[].abc)' <test.yaml | ./j2y
sites:
  qwerty:
    hosts:
    - qwerty.test
  xyz:
    hosts:
    - xyz.test
    repo: null
utilities:
  stuff:
  - thing
  - thing 2

答案 1 :(得分:1)

这将根据您的输入数据工作。

awk 'BEGIN{ print_flag=1 } 
{
    if( $0 ~ /  abc:/ ) 
    {
       print_flag=0;
       next
    } 
    if( $0 ~ /^  [a-zA-Z0-9]+:$/ ) 
    {
        print_flag=1;   
    } 
    if ( print_flag == 1 ) 
        print $0

} ' input.txt

输出:

sites:
  qwerty:
    hosts:
      - qwerty.test
  xyz:
    repo:
    hosts:
      - xyz.test
utilities:
  stuff:
    - thing
    - thing 2

问候!

答案 2 :(得分:0)

一个简单但不是特别灵活的awk解决方案可能是这样的:

awk -v tag="abc:" '/^  [^ ]/ {n=0} /^  [^ ]/ && $1==tag {n=1} (1-n)' input.yaml

为便于阅读而破裂:

  • -v tag="abc:" - 设置一个将从您的输入中删除的变量。
  • /^ [^ ]/ {n=0} - 如果我们发现自己在一条用两个空格缩进的线上,则开始打印。
  • /^ [^ ]/ && $1==tag {n=1} - 但如果该行的第一个字是我们上面指定的标记,停止打印。
  • (n-1) - 如果n = 0,则打印该行。

您可以选择颠倒n的含义,如下所示:

awk -v n=1 -v tag="abc:" '/^  [^ ]/{n=1} /^  [^ ]/ && $1==tag {n=0} n' input.yaml

请注意,使用此用法时,我们需要“填充”n变量,以便打印/^ [^ ]/的第一个实例之前的行。

这不是一个yaml解析器,它是一个文本模式解析器。您可以轻松地为其提供格式不同的完全有效的yaml,因此会被错误地解析。

理论上我可以在awk中对非常有限的实际yaml进行解析。你会遗漏很多数据类型,但你可以写一些比上面的解决方案更灵活的东西。但是,管理一组复杂的awk函数似乎比向工具箱中添加jqy2j等工具要多得多。如果你在yaml中操作文件,我会提交你想要yaml的原生支持,而不是像这样的黑客。

答案 3 :(得分:0)

这可能适合你(GNU sed):

abc

如果它不以abc开头,我们不感兴趣。如果是,并且它是最后一行,请将其删除。否则,追加下一行并检查缩进是否相同。如果不是,则追加另一行并再次检查(如果在任何时候它是最后一行,则删除到目前为止收集的所有行)。如果附加的行与第一行(即从{{1}}开始的行缩进,则删除除最后一行之外的所有行,然后从第一个命令重复。