找到指定字符串时修改行

Dja*_*sef 1 awk text-processing

我有一个看起来像这样的文件

ABC
     2   3   4
     7   9   4
     1   2   5
ABC
     13  11  17
     2   1   1
ABC
     7   9   14
     5   8   2
     9   9   9
     7   1   2
Run Code Online (Sandbox Code Playgroud)

我想在每个“ABC”值的末尾打印“END”这个词,这样文件就会像这样

ABC
     2   3   4
     7   9   4
END  1   2   5
ABC
     13  11  17
END  2   1   1
ABC
     7   9   14
     5   8   2
     9   9   9
END  7   1   2
Run Code Online (Sandbox Code Playgroud)

我尝试了很多但我没有解决它,所以任何人都可以在这里提供帮助。

αғs*_*нιη 7

awk '/^ABC/ && pre { print dpre ORS $0; pre=""; next }
                   { if(pre) print pre; pre=dpre=$0; sub(/ {0,4}/, "END ", dpre) }
END{ if(pre) print dpre }' infile
Run Code Online (Sandbox Code Playgroud)

只有当一行以ABC 字符串开头并且pre还设置了临时变量时,才会执行第一个块,否则将执行下一个块。

END{...}块将只执行一次,并在所有结束后执行。

对于第一行当然还pre没有设置变量,所以将执行第二个块并执行以下操作:

  • 如果里面有东西pre先打印if(pre) print pre(这样我们会延迟打印上一行以检查下一行是否以 开头ABC,因为我们需要END在该行前面添加)

  • 然后我们将该行复制到两个单独的变量中,pre并且dpre(一个将保持不变(稍后我们需要原封不动地打印它),而对于另一个,sub(/ {0,3}/,"END ", dpre)我们将END字符串添加到dpre.

    请注意,使用 {0,4}(零个或最多 4 个空格;4 是从 的长度中获得END<SPC>)我们确保END字符串将始终在前面,并防止在根本没有空格的情况下截断原始行值。


您可以在下面跟踪命令的每次迭代以供您自己理解:

  • 重复
  • 读一行;是否以ABC( /^ABC/)开头?
    • 没有;然后什么都不做,下一个块将被执行;去2-块
    • 是的;是pre设置?
      • 是的,然后做这些
        • 打印dpre变量的内容,然后是单个换行符ORS,然后是当前行本身
        • 空变量pre=""并跳转到REPEAT因为next语句告诉了这一点。
      • 没有;然后什么都不做,下一个块将被执行;去2-块
  • 2-块
    • pre设置?
      • 是的;做这些
        • 打印pre它设置在“ if(pre) print pre”中;
        • 将当前行更新为两个变量pre=dpre=$0
        • END dpre.加上字符串。
      • 没有;做这些
        • 将当前行更新为两个变量pre=dpre=$0
        • END dpre.加上字符串。
  • 如果文件结束;dpre如果已设置,则打印变量的最后状态,否则跳转到REPEAT
  • 结束