2016-07-17 8 views
1

Ich habe überall gesucht, aber ich habe immer noch nicht die Antwort, die ich suche. Ich habe folgende pdb-Datei (file1):Bash - Ersetzen mehrerer Zeilen in einer Datei mit einer einzelnen Zeile aus einer anderen Datei

ATOM  1 N SER A 1  31.848 -5.217 38.114 1.00 39.55 
ATOM  2 CA SER A 1  31.668 -5.130 36.630 1.00 40.83 
ATOM  3 C SER A 1  30.991 -3.833 36.183 1.00 40.24 
ATOM  4 O SER A 1  30.868 -2.883 36.961 1.00 40.08 
ATOM  5 CB SER A 1  30.854 -6.329 36.118 1.00 41.46 
ATOM  6 OG SER A 1  31.600 -7.531 36.190 1.00 44.54 
ATOM  7 N THR A 2  30.605 -3.796 34.906 1.00 39.92 
ATOM  8 CA THR A 2  29.920 -2.658 34.286 1.00 38.97 
ATOM  9 C THR A 2  28.542 -3.116 33.777 1.00 38.40 
ATOM  10 O THR A 2  27.815 -2.341 33.141 1.00 38.79 
ATOM  11 CB THR A 2  30.734 -2.067 33.086 1.00 39.67 
ATOM  12 OG1 THR A 2  31.045 -3.101 32.139 1.00 38.83 
ATOM  13 CG2 THR A 2  32.020 -1.403 33.566 1.00 38.83 

Ich habe auch die folgende Datei nach einiger Berechnung mit gfortran (file2):

1 0.14364205034979632 
2 0.50527753403393372 

Was ich möchte, ist tun Spalte ersetzen 11 von Datei1 mit Spalte 2 von Datei2, solange Spalte 6 von Datei1 gleich Spalte 1 von Datei2 ist. Im Wesentlichen sollte die Ausgabe wie folgt sein:

ATOM  1 N SER A 1  31.848 -5.217 38.114 1.00 0.14364205034979632 
ATOM  2 CA SER A 1  31.668 -5.130 36.630 1.00 0.14364205034979632 
ATOM  3 C SER A 1  30.991 -3.833 36.183 1.00 0.14364205034979632 
ATOM  4 O SER A 1  30.868 -2.883 36.961 1.00 0.14364205034979632 
ATOM  5 CB SER A 1  30.854 -6.329 36.118 1.00 0.14364205034979632 
ATOM  6 OG SER A 1  31.600 -7.531 36.190 1.00 0.14364205034979632 
ATOM  7 N THR A 2  30.605 -3.796 34.906 1.00 0.50527753403393372 
ATOM  8 CA THR A 2  29.920 -2.658 34.286 1.00 0.50527753403393372 
ATOM  9 C THR A 2  28.542 -3.116 33.777 1.00 0.50527753403393372 
ATOM  10 O THR A 2  27.815 -2.341 33.141 1.00 0.50527753403393372 
ATOM  11 CB THR A 2  30.734 -2.067 33.086 1.00 0.50527753403393372 
ATOM  12 OG1 THR A 2  31.045 -3.101 32.139 1.00 0.50527753403393372 
ATOM  13 CG2 THR A 2  32.020 -1.403 33.566 1.00 0.50527753403393372 

Ich habe den folgenden Code:

gawk ' 
FNR==NR { pdb[NR]=$0; next } 
{ 
    split(pdb[FNR],flds,FS,seps) 

    while (flds[6]==$1) { 
    flds[11]=$2 
    for (i=1;i in flds;i++) 
     printf "%s%s", flds[i], seps[i] 
    print "" 
    } 
} 
' "file1" "file2" > "output.pdb" 

Es wird die Arbeit für die erste Zeile von file1 getan und hält den Abstand konstant. Das Problem ist, dass es nicht zu den nächsten Zeilen weitergeht und die erste Zeile wird auch ständig wiederholt. Könnte jemand so freundlich sein, mir zu helfen?

Danke! Ich würde dich für etwas Bier behandeln :)

+0

Sie sind ziemlich verwirrt darüber, wie awk funktioniert und es ist Syntax. Ich empfehle das Buch Effective Awk Programming, 4. Edition von Arnold Robbins, um etwas über awk zu lernen. –

+1

@EdMorton: Ich bin eigentlich neu mit awk und ich habe gerade dieses Stück Code aus dem Internet. Wenn ich Zeit hätte, würde ich gerne Ihre vorgeschlagene Referenz überprüfen. Prost! ~ – ajthealchemist

+0

Es gibt ** FAR ** mehr schlechten Code als guten Code im Internet. Stellen Sie sicher, dass Sie die Quelle auschecken, bevor Sie versuchen, den Code, den Sie online finden, zu verwenden, da er bestenfalls fehlerhaft und oft gefährlich ist. SO ist übersät mit akzeptierten "Antworten", die Ihr Dateisystem oder ähnliches bei einigen Eingaben bereinigen. Oder es könnte für eine Anwendung gut sein, aber schlecht für Ihre. Und natürlich sollten Sie immer zuerst eine empfohlene/vertrauenswürdige Quelle lesen, um ein grundlegendes Verständnis für jedes Werkzeug/jede Sprache zu erhalten, die Sie verwenden möchten, damit Sie eine Chance haben, den guten Code vom schlechten zu trennen. –

Antwort

1

Dies ist ein unglaublich weit verbreitetes Problem, ich bin überrascht, dass Sie keine Lösung finden konnte:

$ awk 'NR==FNR{a[$1]=$2;next} {$11=a[$6]} 1' file2 file1 
ATOM 1 N SER A 1 31.848 -5.217 38.114 1.00 0.14364205034979632 
ATOM 2 CA SER A 1 31.668 -5.130 36.630 1.00 0.14364205034979632 
ATOM 3 C SER A 1 30.991 -3.833 36.183 1.00 0.14364205034979632 
ATOM 4 O SER A 1 30.868 -2.883 36.961 1.00 0.14364205034979632 
ATOM 5 CB SER A 1 30.854 -6.329 36.118 1.00 0.14364205034979632 
ATOM 6 OG SER A 1 31.600 -7.531 36.190 1.00 0.14364205034979632 
ATOM 7 N THR A 2 30.605 -3.796 34.906 1.00 0.50527753403393372 
ATOM 8 CA THR A 2 29.920 -2.658 34.286 1.00 0.50527753403393372 
ATOM 9 C THR A 2 28.542 -3.116 33.777 1.00 0.50527753403393372 
ATOM 10 O THR A 2 27.815 -2.341 33.141 1.00 0.50527753403393372 
ATOM 11 CB THR A 2 30.734 -2.067 33.086 1.00 0.50527753403393372 
ATOM 12 OG1 THR A 2 31.045 -3.101 32.139 1.00 0.50527753403393372 
ATOM 13 CG2 THR A 2 32.020 -1.403 33.566 1.00 0.50527753403393372 

Wenn Sie das weiß über die Erhaltung kümmern Raum:

$ awk 'NR==FNR{a[$1]=$2;next} {sub(/[^[:space:]]+[[:space:]]*$/,a[$6])} 1' file2 file1 
ATOM  1 N SER A 1  31.848 -5.217 38.114 1.00 0.14364205034979632 
ATOM  2 CA SER A 1  31.668 -5.130 36.630 1.00 0.14364205034979632 
ATOM  3 C SER A 1  30.991 -3.833 36.183 1.00 0.14364205034979632 
ATOM  4 O SER A 1  30.868 -2.883 36.961 1.00 0.14364205034979632 
ATOM  5 CB SER A 1  30.854 -6.329 36.118 1.00 0.14364205034979632 
ATOM  6 OG SER A 1  31.600 -7.531 36.190 1.00 0.14364205034979632 
ATOM  7 N THR A 2  30.605 -3.796 34.906 1.00 0.50527753403393372 
ATOM  8 CA THR A 2  29.920 -2.658 34.286 1.00 0.50527753403393372 
ATOM  9 C THR A 2  28.542 -3.116 33.777 1.00 0.50527753403393372 
ATOM  10 O THR A 2  27.815 -2.341 33.141 1.00 0.50527753403393372 
ATOM  11 CB THR A 2  30.734 -2.067 33.086 1.00 0.50527753403393372 
ATOM  12 OG1 THR A 2  31.045 -3.101 32.139 1.00 0.50527753403393372 
ATOM  13 CG2 THR A 2  32.020 -1.403 33.566 1.00 0.50527753403393372 
+0

Danke für diese Antwort, Ed. :) Wenn ich jedoch Ihren zweiten Vorschlag ausprobierte, wird nur die ursprüngliche Datei (Datei1) unverändert angezeigt. – ajthealchemist

+0

@ajthealchemist Möglicherweise verwenden Sie ein altes, nicht POSIX-awk, das die POSIX-Zeichenklasse '[: space:]' nicht erkennen würde. Ersetzen Sie '[^ [: space:]]' durch '[^ \ t]'. Wenn das nicht funktioniert, sagen Sie uns, was "awk --version" ausgibt und veröffentlichen Sie die Ausgabe von 'cat -v file | tr '' '#' | Head -1', damit wir nach Leerzeichen und/oder Steuerzeichen suchen können. –

+0

@ajthealchemist tatsächlich, ich sehe von deiner Frage, dass du eine neue genug Version von gawk verwendest, dass es das 4. arg unterstützt, um zu splitten(), also kann es nicht das Charakterklassenproblem sein so sag uns einfach die awk Version und die Katze Ausgabe. Sie müssen einige Steuerzeichen oder etwas in Ihrer Eingabedatei haben oder Sie haben einfach einen Fehler gemacht, wenn Sie mein Skript kopieren/einfügen. Versuchen Sie auch, sub() zu ändern, um mögliche nachfolgende Leerzeichen zuzulassen: 'sub (/ [^ [: Leerzeichen:]] + [[: Leerzeichen:]] * $ /, a [$ 6])'. –

1

Ich nehme an, dass file1 nach Spalte 6 sortiert ist.

join -1 6 -2 1 file1 file2 -o 1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,1.9,1.10,2.2 | column -t 

Ausgang:

 
ATOM 1 N SER A 1 31.848 -5.217 38.114 1.00 0.14364205034979632 
ATOM 2 CA SER A 1 31.668 -5.130 36.630 1.00 0.14364205034979632 
ATOM 3 C SER A 1 30.991 -3.833 36.183 1.00 0.14364205034979632 
ATOM 4 O SER A 1 30.868 -2.883 36.961 1.00 0.14364205034979632 
ATOM 5 CB SER A 1 30.854 -6.329 36.118 1.00 0.14364205034979632 
ATOM 6 OG SER A 1 31.600 -7.531 36.190 1.00 0.14364205034979632 
ATOM 7 N THR A 2 30.605 -3.796 34.906 1.00 0.50527753403393372 
ATOM 8 CA THR A 2 29.920 -2.658 34.286 1.00 0.50527753403393372 
ATOM 9 C THR A 2 28.542 -3.116 33.777 1.00 0.50527753403393372 
ATOM 10 O THR A 2 27.815 -2.341 33.141 1.00 0.50527753403393372 
ATOM 11 CB THR A 2 30.734 -2.067 33.086 1.00 0.50527753403393372 
ATOM 12 OG1 THR A 2 31.045 -3.101 32.139 1.00 0.50527753403393372 
ATOM 13 CG2 THR A 2 32.020 -1.403 33.566 1.00 0.50527753403393372 

aktualisieren:

Mit bash printf:

printf "%s %6.d %-3s %s %s %s  %s %s %s %s %s\n" $(join -1 6 -2 1 file1 file2 -o 1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,1.9,1.10,2.2) 

Ausgang:

 
ATOM  1 N SER A 1  31.848 -5.217 38.114 1.00 0.14364205034979632 
ATOM  2 CA SER A 1  31.668 -5.130 36.630 1.00 0.14364205034979632 
ATOM  3 C SER A 1  30.991 -3.833 36.183 1.00 0.14364205034979632 
ATOM  4 O SER A 1  30.868 -2.883 36.961 1.00 0.14364205034979632 
ATOM  5 CB SER A 1  30.854 -6.329 36.118 1.00 0.14364205034979632 
ATOM  6 OG SER A 1  31.600 -7.531 36.190 1.00 0.14364205034979632 
ATOM  7 N THR A 2  30.605 -3.796 34.906 1.00 0.50527753403393372 
ATOM  8 CA THR A 2  29.920 -2.658 34.286 1.00 0.50527753403393372 
ATOM  9 C THR A 2  28.542 -3.116 33.777 1.00 0.50527753403393372 
ATOM  10 O THR A 2  27.815 -2.341 33.141 1.00 0.50527753403393372 
ATOM  11 CB THR A 2  30.734 -2.067 33.086 1.00 0.50527753403393372 
ATOM  12 OG1 THR A 2  31.045 -3.101 32.139 1.00 0.50527753403393372 
ATOM  13 CG2 THR A 2  32.020 -1.403 33.566 1.00 0.50527753403393372 
+0

Danke für diesen Cyrus :) Allerdings sind PDB-Dateien sehr empfindlich in Bezug auf Abstände. Ich muss noch die Abstände in file1 beibehalten. – ajthealchemist

+0

Danke für die Mühe cyrus, aber das ist nicht nur die Antwort, die ich suche. +1 für Ihre Mühe Kumpel :) – ajthealchemist

0

Diese Lösung ist spezifisch gaffen (siehe Defining Fields by Content) und übernimmt file2 zwei Spalten durch Leerzeichen getrennt hat Ausgang je nach Anforderung

awk 'BEGIN {FPAT = "([[:space:]]*[[:alnum:][:punct:][:digit:]]+)"; OFS = "";} FNR==NR{a[$1]=$2; next} {$11=a[$6+0]} {print}' file2 file1 
  • {$11=a[$6+0]} so dass Werte von $6 wie „1“ und "zu erhalten 2" wird gegen Werte in Array übereinstimmen a wie "1" und "2" in einem numerischen Kontext statt String-Vergleich (Danke @Ed Morton für die Erklärung)

Referenzen:

+1

danke, wird die Antwort aktualisieren – Sundeep

+0

Gern geschehen. Tun Sie dies nicht mit FPAT, aber es ist der falsche Ansatz, da es gawk-spezifisch, cludgy und begrenzt in der Anwendbarkeit ist, während es eine weit bessere allgemeine Lösung gibt, wenn Sie gawk (4. arg to split) verwenden und es notwendig ist (was es in diesem Fall nicht ist). Die falsche Antwort wird in der Frage akzeptiert, auf die Sie verweisen. –

+1

danke nochmal, hatte gerade eine antwort gesucht und zusammengenäht .. das war eine lernerfahrung und da gibt es noch mehr zu lernen von deinen kommentaren und antwort ... – Sundeep