Ich habe es auf viele Arten versucht, aber kann immer noch nicht erreichen, was ich will. Tut mir leid, ich lerne noch.
Was ich will, ist Folgendes:
Datei A.txt
5844
6069
6303
6309
Datei B.txt
// some comment
// some explanation
100,5,3,8,,,
500,5,44,8,,,
//2500,5,2,8,,,
2121,5,2,8,,,
5535,5,4,6069,,,
5844,1,4,5844,,,
5900,5,2,8,,,
6069,5,4,8,,,
Ich möchte die gesuchte Nummer aus A.txt ändern und die Zeile in B.txt auskommentieren. Manchmal erscheint die gesuchte Nummer in einer anderen Spalte, sodass nur die erste Spalte geändert wird.
Ergebnis:
// some comment
// some explanation
100,5,3,8,,,
500,5,44,8,,,
2500,5,2,8,,,
2121,5,2,8,,,
5535,5,4,6069,,,
//5844,1,4,5844,,,
5900,5,2,8,,,
//6069,5,4,8,,,
Ich habe es versucht und manchmal ging es schief und ich habe auch die andere Spalte geändert. Dann habe ich so etwas verwendet, es ist sehr lang und nicht einfach zu ändern,
awk -F ',' '/^5844/ && $1="5844"{$1="//5844"}1' b.txt > c.txt; cp c.txt ba.txt; rm -rf b.txt; mv ba.txt b.txt
und manchmal wird auch das Trennzeichen , entfernt.
Bitte helfen Sie, vielen Dank.
Antwort1
$ awk -F , 'FNR==NR { data[$1]=1; next } $1 in data { $0 = "//" $0 }; 1' 'File A.txt' 'File B.txt'
500,5,4,8,,,
5535,5,4,6069,,,
2121,5,4,8,,,
//5844,5,4,5844,,,
//6069,5,4,8,,,
Was ich hier mache, ist, zuerst die Zahlen aus File A.txt
als Schlüssel in das assoziative Array einzulesen data
. Dann teste ich jedes erste Feld aus , um File B.txt
zu sehen, ob es ein Schlüssel in ist data
oder nicht. Wenn ja, stelle ich es //
der aktuellen Zeile voran. Alle Zeilen, ob geändert oder nicht, werden dann gedruckt.
Der FNR==NR
Test ist nur beim Lesen aus der ersten Datei in der Befehlszeile wahr und der Block endet mit next
. Dies bedeutet, dass der erste Block nur für die erste Datei ausgeführt wird, während der zweite Block für die zweite Datei ausgeführt wird, wenn das erste Feld ein Schlüssel im data
Array ist.
Das 1
am Ende löst die Ausgabe aus und könnte durch ersetzt werden { print }
.
Das Obige wird nurhinzufügen //
zu den Zeilen in der zweiten Datei, die mit den Zahlen in der ersten Datei übereinstimmen. Um auchentfernen //
aus Zeilennichtabgeglichen (um also Ihre aktualisierte Frage zu bearbeiten):
$ cat 'File B.txt'
// some comment
// some explanation
100,5,3,8,,,
500,5,44,8,,,
//2500,5,2,8,,,
2121,5,2,8,,,
5535,5,4,6069,,,
5844,1,4,5844,,,
5900,5,2,8,,,
6069,5,4,8,,,
$ awk -F , 'FNR==NR { data[$1]=1; next } FNR > 2 { if ($1 in data) $0 = "//" $0; else sub("^//","") }; 1' 'File A.txt' 'File B.txt'
// some comment
// some explanation
100,5,3,8,,,
500,5,44,8,,,
2500,5,2,8,,,
2121,5,2,8,,,
5535,5,4,6069,,,
//5844,1,4,5844,,,
5900,5,2,8,,,
//6069,5,4,8,,,
Der awk
Befehl geht davon aus, dass Sie die ersten beiden Zeilen von unverändert durchgeben möchten File B.txt
(das FNR > 2
erledigt der Test). Der FNR > 2
Block prüft, ob die Zahl ein eingegebener Schlüssel ist data
oder nicht. Wenn dies der Fall ist, wird die Zeile auskommentiert. Wenn nicht, //
wird jeder am Zeilenanfang mit entfernt sub()
.
Stattdessen FNR > 2
können Sie verwenden, /^\/\/ /
um zu prüfen, ob am Anfang der Datei ein Kommentar steht. Dies würde erfordern, dass alle derartigen Kommentare immer mit beginnen, //
gefolgt von einem Leerzeichen.
Die Sondervariablen NR
und FNR
enthalten die Anzahl der bisher insgesamt ( NR
) und in der aktuellen Datei ( FNR
) gelesenen Zeilen.
Die Kommas würden „verschwinden“, wenn ich nur das erste Feld mit ändern würde, da dadurch der Datensatz mit dem aktuellen Wert von (standardmäßig ein Leerzeichen) $1 = "//" $1
neu gebildet würde . Sie können dies verhindern, indem Sie verwenden, wodurch das Kommazeichen (oder das Zeichen, das Sie mit in der Befehlszeile verwenden) gesetzt wird .OFS
BEGIN { OFS=FS }
OFS
-F