awk: 新しいレコードの作成と NR の更新

awk: 新しいレコードの作成と NR の更新

解決すべき特定の問題ではなく、一般的な質問に近い。

このようなファイルがあるとしましょう。

entry 1
entry 3
entry 6

欠落している項目を埋めたいですawk。新しいレコードを挿入してNRを更新できますか?アイデアは次のとおりです。

awk 'BEGIN {print "NR","line"
     $2!=NR {<create record> "entry",NR ; <repeat commands on same record>}
     {print NR,$0}' file

したがって、コマンドは次のようになります。

  • 新しいレコードの挿入
  • 新しいレコードに一致するNRを提供し、次のレコード番号を更新してください。
  • 条件を再確認する機能(たとえば、entry 6到達すると生成されるentry 4entry 5失われたことを認識する必要があります。したがって、記録された条件を再確認する必要がありますentry 6

希望の出力

NR line
1  entry 1
2  entry 2
3  entry 3
4  entry 4
5  entry 5
6  entry 6

答え1

あなたできない入力ファイルのステップで新しい入力レコードを作成します。新しい入力レコードを生成するとは、次のコードを意味します。

awk '
    {
        print $0
        magic to create a new record with contents "Foo"
    }
'

元のレコードを印刷してから、「Foo」を印刷する無限ループに入ります。定義によれば、awkは各入力レコードに対して上記のコードを一度実行するためです。

入力レコードから出ているか内部的に生成されても、文字列からコードを実行できます。たとえば、次のようになります。

awk '
    {
        prt($0)
        other stuff
        prt("Foo")
    }
    function prt(str) {
        print str
    }
'

しかし、これは実際に新しい入力レコードを生成するのとは異なります。

最初のパスで一時ファイルを作成して書き込む2段階のアプローチを実行することもできます。これにより、2番目のパスから一時ファイルを読み取ると、新しく印刷された文字列が入力レコードとして表示されます。

NRあなたは「それでも」の意味を過負荷/乱用しています。NR個数です入力する読み取った履歴と数を印刷しようとしています。出力印刷された記録はまったく異なる問題です。組み込み変数はありません。以下NRのように台無しにするのではなく、別の変数で直接追跡するのが簡単だからです。onr

$ cat file
awk '
    BEGIN { print "NR", "onr", "line" }
    NR == 1 { val = $2-1 }
    {
        for (val++; val<$2; val++) {
            processString($1 FS val)
        }
        processString($0)
    }

    function processString(str) {
        print NR, ++onr, str
    }
' file
NR onr line
1 1 entry 13
2 2 entry 14
2 3 entry 15
3 4 entry 16
3 5 entry 17
3 6 entry 18

しかし、新しい入力レコードを生成するわけではないので(いつものように)組み込み変数の値を調整する試みはまったく不適切ですNR。代わりに、新しい出力レコードを作成し、名前付きカスタム変数の合計出力レコード数を追跡しますonr

NR出力におよびを追加し、onrサンプル入力を次のように変更しました。

$ cat file
entry 13
entry 15
entry 18

実際には、3つの別々のデータ項目が使用されることを強調することが重要です。

  1. NR=レコード数を入力し、
  2. onr=出力レコード数、
  3. val=各レコードに対して印刷する$ 2の値

プログラムの明確さ、凝集性、結合性、保守性などのために、これらのいずれにも過負荷をかけないことが最善です。

答え2

編集+警告

以下のコメントで述べたようにNRそうですFNR定義によるとカウンター履歴を入力してくださいしたがって、変わらずに維持する必要があります。 (引用する:友達マニュアル)制限なく操作できますが、下記のようにこれらの値を操作しないでください。この回答は警告として残しておきます。


いいですね。 Jeff Schaller、Romeo Ninov、Fra-sanのコメントのおかげで、次のことが機能します。

  • 手動で追加NRするFNR
  • 適切に定義されたループを使用してくださいNR。 /FNR

可能なスクリプト:

awk 'BEGIN {print "NR","line"}
     $2 > NR { for (NR; NR<$2; NR++) print NR,"entry "NR }
     {print NR,$0}' infile

複数の入力ファイルがある場合は、正しい番号付けを保証するために次のようNRに置き換えられます(正しい合計を保証するために使用できます)。FNRNR++

これはNR++更新をシミュレートしますNRが、ループは同じレコードでコマンドを再実行することをシミュレートします(問い合わせの疑いとは反対)。これは完全に一致する()nextを使用して新しく作成されたレコードのように見えます。NRFNR

関連情報