指定された文字列が見つかった場合、行を修正します。

指定された文字列が見つかった場合、行を修正します。

次のファイルがあります

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

各「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

多くの努力をしましたが、何の効果もありませんでした。誰でも助けることができますか?

ベストアンサー1

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

最初のブロックは、行が次に始まる場合にのみ実行されます。ABC 文字列と一時変数preまた設定されます。それ以外の場合は、次のブロックが実行されます。

このEND{...}ブロックは、すべてのジョブが完了した後に一度だけ実行されます。

もちろん、最初の行はまだpre変数がまだ設定されていないので、次のような2番目のブロックが実行されます。

  • 内容があればpreまず印刷します。 (これを行うと、その行の前if(pre) print preに追加する必要があるため、次の行が内容で始まることを確認するために前の行の印刷を遅らせます。)ABCEND

  • その後、行を2つの別々の変数にコピーしpredpreそのうちの1つは変更されずに保持されます(後で変更せずに印刷する必要があります))、他の変数にはsub(/ {0,3}/,"END ", dpre)文字列ENDdpre

    {0,4}(0または最大4つのスペース、4はの長さから取得されますEND<SPC>)を使用すると、END文字列が常に先頭に追加され、スペースがまったくない場合に元の行値が切り捨てられるのを防ぐことができます。


理解を助けるために、以下のコマンドの各繰り返しを追跡できます。

  • 繰り返す
  • 一行をお読みください。ABC/^ABC/)?
    • いいえ;何もしないと、次のブロックが実行されます。第二作品
    • はい;設定されていますかpre
      • はいその後、次の作業を行います。
        • 変数の内容dpre、単一の改行文字ORS、現在の行自体を印刷します。
        • 変数を空にしてpre=""次にジャンプ繰り返すなぜなら、next声明がそれを教えてくれるからです。
      • いいえ;何もしないと、次のブロックが実行されます。第二作品
  • 第二作品
    • 設定されていますかpre
      • はい;これらをしなさい
        • 印刷設定は「」preにあります。if(pre) print pre
        • 現在の行を2つの変数に更新しますpre=dpre=$0
        • プレフィックスEND ひもdpre
      • いいえ;これらをしなさい
        • 現在の行を2つの変数に更新しますpre=dpre=$0
        • プレフィックスEND ひもdpre
  • ファイルの終わりのdpre場合、変数が設定されている場合は最終ステータスを印刷します。繰り返す
  • 終わる

おすすめ記事