NRとFNRとは何ですか?「NR == FNR」は何を意味しますか?


83

を使用してファイル比較を学習していますawk

以下のような構文を見つけました、

awk 'NR==FNR{a[$1];next}$1 in a{print $1}' file1 file2

NR==FNRこれの意味がわからなかったのですか?試してみるとFNR==NR、同じ出力が得られますか?

それは正確に何をしますか?


20
あなたがあれば驚くだろうa==bb==a同じ結果を生成しましたか?
エド・モートン

回答:


91

awkではFNR、現在のファイルのレコード番号(通常は行番号)をNR参照し、合計レコード番号を参照します。演算子==は比較演算子であり、周囲の2つのオペランドが等しい場合にtrueを返します。

これは、各ファイルの最初の行で1にリセットされるが、増加し続けるNR==FNRため、条件は最初のファイルに対してのみ真であることを意味しFNRますNR

このパターンは通常、最初のファイルに対してのみアクションを実行するために使用されます。next彼らは唯一の最初以外のファイル上で実行されているので、それ以上のコマンドは、スキップされるブロック手段の内部。

条件FNR==NRは、と同じ2つのオペランドを比較するNR==FNRため、同じように動作します。


3
"="は、同等性をテストするために使用されることもあれば、割り当てを行うために使用されることもあります。二重等号が割り当てに使用されていた場合、FNR == NRはNR == FNRとは異なります。したがって、このaskerのように、awkに慣れていない人にとっては、同じかどうかを尋ねるのが妥当なようです。
トッドウォルトン

@ToddWalton良い点です!別の例:a='3x'; if [[ $a == 3* ]]; then echo yes; fiそして、の両側を切り替えることはできません==
ウォルター

@WalterAはい、そうです(少なくとも、Bashでは)。私の答えに何か改善を提案していますか?
トムフェネク2018

1
いいえ、あなたの答えは大丈夫です。コミュニティが私たちの答えを同じように気に入っているのを見るのが本当に好きです。私たちはさまざまなスタイルを使用しており、どちらも非常に役立つと見なされています。私はあなたに賛成票を与えたので、今のところ私たちは同じ数の賛成票を持っています。
Walter A

70

file1にもあるfile2のキー(行の最初の単語)を探します。
ステップ1:配列aにファイル1の最初の単語を入力します。

awk '{a[$1];}' file1

手順2:同じコマンドで配列aを入力し、ファイル2を無視します。このために、現在の入力ファイルの数でこれまでのレコードの総数を確認してください。

awk 'NR==FNR{a[$1]}' file1 file2

ステップ3:}ファイル1を解析するときに発生する可能性のあるアクションを無視する

awk 'NR==FNR{a[$1];next}' file1 file2 

ステップ4:配列aで見つかったときにfile2のキーを出力する

awk 'NR==FNR{a[$1];next} $1 in a{print $1}' file1 file2

4
このワンライナーの見事なテイクダウン。手順1のセミコロンは必要ですか?
Tomasz Gandor 2017

2
@TomaszGandorステップ1ではセミコロンは必要ありません。ステップ3で追加できたかもしれません;nextが、奇妙な追加です(nextステップ3でセミコロンを追加して必要とするようなものです)。ステップ1はawk '{a[$1]} END { for (k in a) { print "a[k]=" k } }' file1。でテストできます。
Walter A

43

見上げるNRFNRawkでのマニュアルと、その後の下で条件が何であるかを自問してみてくださいNR==FNR、次の例では:

$ cat file1
a
b
c

$ cat file2
d
e

$ awk '{print FILENAME, NR, FNR, $0}' file1 file2
file1 1 1 a
file1 2 2 b
file1 3 3 c
file2 4 1 d
file2 5 2 e

処理中のファイル番号を印刷することもできますか?そのための組み込み変数はありますか?(私はNRが1である、我々はそのための変数を作成することができます知っているし、それをすべての時間をインクリメント)
レオ

GNU awkでは、その変数はARGINDですFNR==1{ print ++file_nr }。それ以外の場合は、を実行できます。
エド・モートン

可能であれば、別の質問で質問に答えるのはそれほど効率的ではありません;)
Florian Castelain

私は質問をしませんでした、私はOPの質問への答えを得る方法を示しました。
エド・モートン

20

awk組み込み変数があります。

NR -処理されたレコードの総数を示します。

FNR -各入力ファイルのレコードの総数を示します。


14

ファイルa.txtとb.txtがあると仮定します。

cat a.txt
a
b
c
d
1
3
5
cat b.txt
a
1
2
6
7

NRとFNRはawkの組み込み変数であることに注意してください。NR-処理されたレコードの総数を示します。(この場合、a.txtとb.txtの両方)FNR-各入力ファイルのレコードの総数を示します(a.txtまたはb.txtのいずれかのレコード)

awk 'NR==FNR{a[$0];}{if($0 in a)print FILENAME " " NR " " FNR " " $0}' a.txt b.txt
a.txt 1 1 a
a.txt 2 2 b
a.txt 3 3 c
a.txt 4 4 d
a.txt 5 5 1
a.txt 6 6 3
a.txt 7 7 5
b.txt 8 1 a
b.txt 9 2 1

「次へ」を追加して、NR == FNRと一致する最初の一致をスキップします

b.txtおよびa.txt

awk 'NR==FNR{a[$0];next}{if($0 in a)print FILENAME " " NR " " FNR " " $0}' a.txt b.txt
b.txt 8 1 a
b.txt 9 2 1

b.txtにはありますが、a.txtにはありません

 awk 'NR==FNR{a[$0];next}{if(!($0 in a))print FILENAME " " NR " " FNR " " $0}' a.txt b.txt
b.txt 10 3 2
b.txt 11 4 6
b.txt 12 5 7

awk 'NR==FNR{a[$0];next}!($0 in a)' a.txt b.txt
2
6
7
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.