如何排除块中具有特定字符串条件的 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。
我试图在特定情况发生时排除文本块。
文件的布局如下:
- 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。