Ich lerne Dateivergleich mit awk
.
Ich fand Syntax wie unten,
awk 'NR==FNR{a[$1];next}$1 in a{print $1}' file1 file2
Ich konnte nicht verstehen, welche Bedeutung NR==FNR
dies hat. Wenn ich es FNR==NR
dann versuche, bekomme ich auch die gleiche Ausgabe?
Was genau macht es?
a==b
undb==a
das gleiche Ergebnis erzeugt?Two-file Processing
auf backreference.org/2010/02/10/idiomatic-awkAntworten:
In awk
FNR
bezieht sich auf die Datensatznummer (normalerweise die Zeilennummer) in der aktuellen Datei undNR
auf die gesamte Datensatznummer. Der Operator==
ist ein Vergleichsoperator, der true zurückgibt, wenn die beiden umgebenden Operanden gleich sind.Dies bedeutet, dass die Bedingung
NR==FNR
nur für die erste Datei gilt, daFNR
sie jedoch für die erste Zeile jeder Datei auf 1 zurückgesetzt wirdNR
weiter zunimmt.Dieses Muster wird normalerweise verwendet, um Aktionen nur für die erste Datei auszuführen. Das
next
Innere des Blocks bedeutet, dass alle weiteren Befehle übersprungen werden, sodass sie nur für andere als die ersten Dateien ausgeführt werden.Die Bedingung
FNR==NR
vergleicht dieselben zwei Operanden wieNR==FNR
, verhält sich also genauso.quelle
a='3x'; if [[ $a == 3* ]]; then echo yes; fi
und Sie können nicht beide Seiten von wechseln==
.Suchen Sie in Datei2 nach Schlüsseln (erstes Wort der Zeile), die sich auch in Datei1 befinden.
Schritt 1: Füllen Sie Array a mit den ersten Wörtern von Datei 1:
awk '{a[$1];}' file1
Schritt 2: Füllen Sie Array a und ignorieren Sie Datei 2 im selben Befehl. Überprüfen Sie dazu die Gesamtzahl der bisherigen Datensätze mit der Nummer der aktuellen Eingabedatei.
awk 'NR==FNR{a[$1]}' file1 file2
Schritt 3: Ignorieren Sie Aktionen, die
}
beim Parsen von Datei 1 auftreten könnenawk 'NR==FNR{a[$1];next}' file1 file2
Schritt 4: Drucken Sie den Schlüssel von Datei2, wenn er im Array gefunden wird. A.
awk 'NR==FNR{a[$1];next} $1 in a{print $1}' file1 file2
quelle
;next
eine seltsame Ergänzung (möchtenext
das Semikolon in Schritt 3 hinzufügen und benötigen). Sie können Schritt 1 mit testenawk '{a[$1]} END { for (k in a) { print "a[k]=" k } }' file1
.Nachschlagen
NR
undFNR
in der awk Handbuch und dann fragen Sie sich , was die Bedingung , unter dem sichNR==FNR
in dem folgenden Beispiel:$ 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
quelle
ARGIND
, sonst können Sie tunFNR==1{ print ++file_nr }
.Es gibt
awk
integrierte Variablen.NR
- Es gibt die Gesamtzahl der verarbeiteten Datensätze an.FNR
- Es gibt die Gesamtzahl der Datensätze für jede Eingabedatei an.quelle
Angenommen, Sie haben Dateien a.txt und b.txt mit
cat a.txt a b c d 1 3 5 cat b.txt a 1 2 6 7
Denken Sie daran, dass NR und FNR awk integrierte Variablen sind. NR - Gibt die Gesamtzahl der verarbeiteten Datensätze an. (in diesem Fall sowohl in a.txt als auch in b.txt) FNR - Gibt die Gesamtzahl der Datensätze für jede Eingabedatei an (Datensätze in a.txt oder 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
Lassen Sie "Weiter" hinzufügen, um die erste Übereinstimmung mit NR == FNR zu überspringen
in b.txt und in 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
in b.txt aber nicht in 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
quelle