awk select line with variable, kann keine solche Datei öffnen

Sep 07 2020

Ich kämpfe mit einem grundlegenden awk-Befehl.

Datei 1:

AB253828.1
AB253829.1
AB253830.1
AB253831.1

Datei 2:

accession   accession.version   taxid   gi
A00001  A00001.1    10641   58418
A00002  A00002.1    9913    2
A00003  A00003.1    9913    3
A00004  A00004.1    32630   57971
A00005  A00005.1    32630   57972
A00006  A00006.1    32630   57973
A00008  A00008.1    32630   57974
A00009  A00009.1    32630   57975
A00010  A00010.1    32630   57976

Beide Dateien haben> 1 000 000 Zeilen

Ich möchte die Spalten 2 und 3 von Datei 2 drucken, wenn Spalte 2 den Mustern von Datei 1 entspricht. Ich habe viele Möglichkeiten ausprobiert, aber keine funktioniert ...

for ACC in $(cat file1.txt) do #ACC1=$(echo "\"$ACC\"") awk -v OFS='\t'-v z="$ACC" '{ if($2 == z) { print $2,$3 } }' file2.txt
done

ich habe

awk: {if ($ 2 == z) {print kann nicht geöffnet werden $2,$3}} file2.txt (Keine solche Datei oder kein solches Verzeichnis)

Ich habe nachgesehen, Datei2 ist da. Ich nehme an, mein Problem ist die Variable z, aber ich kann keine Lösung finden.

Antworten

2 tripleee Sep 07 2020 at 21:01

Das unmittelbare Problem besteht darin, dass vor der zweiten -vOption ein Leerzeichen fehlt . (Schauen Sie genau hin: Sie setzen das OFS auf \t-vund dann denkt Awk, dass z="$ACC"es Ihr eigentliches Awk-Skript ist, und sucht nach einer Datei mit dem Namen ... des Inhalts Ihres Awk-Skripts und beschwert sich über deren Fehlen.) Aber Sie möchten wirklich überarbeiten das gründlicher.

awk -v OFS='\t' 'NR==FNR { z[$1]++; next }
    $2 in z { print $2,$3 }' file1.txt file2.txt

Hierbei wird ein allgemeines Awk-Idiom verwendet, um die erste Datei in den Speicher einzulesen und dann die Datensätze aus der zweiten auszudrucken, deren zweites Feld als Eintrag in der ersten Datei vorhanden war. Dies sollte um Größenordnungen schneller sein und natürlich die Leselinien trivial mitfor Antipattern fixieren .

Wenn die erste Datei zu groß ist, um sofort in den Speicher zu passen, partitionieren Sie sie möglicherweise in kleinere Teile (z. B. jeweils 500.000 Zeilen?) Und führen Sie diese auf jeder dieser Dateien separat aus. Es sollte leicht zu erkennen sein, wann Awk so viel Speicher verbraucht, dass Ihr System anfängt zu krachen. Behalten Sie zumindest in den ersten Läufen ein topähnliches Überwachungstool im Auge und beenden Sie den Vorgang, wenn er sich schlecht verhält.