解決すべき特定の問題ではなく、一般的な質問に近い。
このようなファイルがあるとしましょう。
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 4
がentry 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つの別々のデータ項目が使用されることを強調することが重要です。
NR
=レコード数を入力し、onr
=出力レコード数、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
に置き換えられます(正しい合計を保証するために使用できます)。FNR
NR++
これはNR++
更新をシミュレートしますNR
が、ループは同じレコードでコマンドを再実行することをシミュレートします(問い合わせの疑いとは反対)。これは完全に一致する()next
を使用して新しく作成されたレコードのように見えます。NR
FNR