如何排除块中具有特定字符串条件的 awk 文本块

How to exclude awk text block that has specific condition of strings in the block

我试图在特定情况发生时排除文本块。

文件的布局如下:

- name: Sedan
  tags:
  - DIGIT
  - ABC
  - DEF
  - YES
- name: Combi
  tags:
  - DIGIT
  - ABC
  - DEF
  - NO
- nane: SUV
  tags:
  - DIGIT
  - DEF
  - YES
- nane: OTHER
  tags:
  - DIGIT
  - ABC
  - YES

条件是:ABC && !DEF 因此,只打印块中只有 ABC 的文本块。

它应该给我这个打印输出:

- nane: OTHER
  tags:
  - DIGIT
  - ABC
  - YES

我的第一次尝试是这样的:

awk '/^- name:/ { if (found && value) {print value} found=value="" } { value=(value?value ORS:"")[=12=] } /ABC/ && !/DEF/ { found=1 } END { if (found && value) { print value } }' file

但是上面的尝试打印了具有两种模式的每个文本块!

以下两种解决方案都有效,这就是我如何使用它对多个文件执行此操作:

for i in `find /home/ -mindepth 1 -type f ! -empty`; do ln=`awk -v RS='(^|\n)- ' '/- ABC(\n|$)/ && !/- DEF(\n|$)/ {printf "- %s\n", [=13=]}' $i; printf $i`; echo -e $ln"\n" | sed -n -e 's/^.*file: //p' | grep txt ; done

谢谢

使用gnu-awk,您可以在每个块中使用第一个-将文件分割成记录:

awk -v RS='(^|\n)- ' '/- ABC/ && !/- DEF/ {printf "- %s", [=10=]}' file

- nane: OTHER
  tags:
  - DIGIT
  - ABC
  - YES

或者更准确地说:

awk -v RS='(^|\n)- ' '
/- ABC(\n|$)/ && !/- DEF(\n|$)/ {printf "- %s", [=11=]}
' file

我通常不喜欢管道中 awk/sed/grep 的多个实例,但这个问题似乎适合它。首先,插入空行作为记录分隔符。然后过滤。然后去掉空行:

 awk '/^-/{print ""} 1' input | awk '/ABC/ && !/DEF/' RS= | sed '/^$/d'

awk 的某些版本允许多字符 RS,但此管道似乎足够简单,可以与不支持该扩展的 awk 的那些实现一起使用。

但似乎更好的解决方案是将 yaml 转换为 json,然后使用 jq 过滤,然后再转换回 yaml。