awk 范围模式中的反向引用

Backreferences in awk range pattern

我有一个脚本,其中包含有用的提示,可以让我提醒自己经常忘记的各种事情。目前看起来像这样(但有更多有用的提示):

#!/bin/bash
awk 'BEGIN{IGNORECASE = 1}/^.*''.*:$/,/^$/' <<'_EOF'

tip_header:
  tip1:
    actual tip
  <-- white space to here
  tip2:
    another tip
  <-- white space to here
  something:
    else with \weird $characters^~

another_header:
  tip1:
    tip1 for another_header

_EOF

然后我调用 tips tip_header 打印出 tip_header:another_header: 之前的空行之间的所有内容(tip2: 之前的行有空格,所以不为空)或 tips tip1 从每个 tip1: 行打印到下一个空行。

我想更改 awk 表达式,使 endpat 匹配第一个空行,缩进与 begpat 中的相同,这样调用 tips tip1 就不会t 也打印出 tip2。 类似于:

awk 'BEGIN{IGNORECASE = 1}/^([[:blank:]]*).*''.*:$/,/^$/' <<'_EOF'

但这不起作用(我不确定 how/if 是否可以在 awk 或其变体中使用反向引用)。我不反对用其他可以进行多行模式匹配的东西来替换 awk。

编辑: 运行 tips tip1 的当前输出是

brett@brett:~/tmp$ ./tips tip1
  tip1:
    actual tip

  tip2:
    another tip

  something:
    else with \weird $characters^~

  tip1:
    tip1 for another_header

期望的输出是

brett@brett:~/tmp$ ./tips tip1
  tip1:
    actual tip

  tip1:
    tip1 for another_header

同时保持

brett@brett:~/tmp$ ./tips tip_header
tip_header:
  tip1:
    actual tip

  tip2:
    another tip

  something:
    else with \weird $characters^~

首先,我要坚持@tripleee 是正确的,你应该使用适当的工具来解析 yaml 文件。

如果你真的想使用 awk,我会做一些像这样丑陋的事情(我试图做一个适用于任何 awk 版本的代码):

#!/bin/bash
awk -v search="" -F '' '
    BEGIN{IGNORECASE = 1}
    (!pos_char)&&([=10=] ~ (search ".*:")){
    pos_char=1;
        while($pos_char==" "){
            pos_char+=1
        }
        print; next
    } 
    prev_line == "" && NF && pos_char{
        if(NF<pos_char){
            pos_char = 0; next
        }
        for(i=1; i<=pos_char; i++){
            if($i != " "){
                pos_char = 0; next
            }
        }
    }
    pos_char{prev_line=[=10=];print}
' << '_EOF'

tip_header:
  tip1:
    actual tip

  tip2:
    another tip
with carriage return

  something:
    else with \weird $characters^~

another_header:
  tip1:
    tip1 for another_header

_EOF

仅当您使用空格缩进时才有效。 至少你可以用这个方法去除空行上难看的空白字符。

输出:

$ ./tips tip
tip_header:
  tip1:
    actual tip

  tip2:
    another tip
with carriage return

  something:
    else with \weird $characters^~

  tip1:
    tip1 for another_header

$ ./tips tip_header
tip_header:
  tip1:
    actual tip

  tip2:
    another tip
with carriage return

  something:
    else with \weird $characters^~

$ ./tips tip1
  tip1:
    actual tip

  tip1:
    tip1 for another_header

$ ./tips tip2
  tip2:
    another tip
with carriage return