web-dev-qa-db-ja.com

awkの「NR == FNR」とは何ですか?

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

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

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

これでNR==FNRの重要性が理解できませんでしたか? FNR==NRを試してみると、同じ出力が得られますか?

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

51
Amit

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

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

このパターンは通常、最初のファイルに対してのみアクションを実行するために使用されます。ブロック内のnextは、それ以降のコマンドがスキップされることを意味するため、最初のコマンド以外のファイルでのみ実行されます。

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

64
Tom Fenech

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
52
Walter A

AwkマニュアルでNRFNRを検索し、次の例で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
33
Ed Morton

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

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

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

10
sat

ファイル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