【问题标题】:How to exclude awk text block that has specific condition of strings in the block如何排除块中具有特定字符串条件的awk文本块
【发布时间】:2021-09-29 03:21:22
【问题描述】:

当某种情况发生时,我试图排除文本块。

文件具有以下布局:

- 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:"")$0 } /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", $0}' $i; printf $i`; echo -e $ln"\n" | sed -n -e 's/^.*file: //p' | grep txt ; done

谢谢

【问题讨论】:

    标签: regex awk


    【解决方案1】:

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

    awk -v RS='(^|\n)- ' '/- ABC/ && !/- DEF/ {printf "- %s", $0}' file
    
    - nane: OTHER
      tags:
      - DIGIT
      - ABC
      - YES
    

    或者更准确地说:

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

    【讨论】:

    • 是的,它有效!我还将更新关于如何在 for 循环中使用它的问题。
    【解决方案2】:

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

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-03-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多