GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Ersetzen Sie Zeilen in einer Datei durch Zeilen in einer anderen durch die Zeilennummer

Mit awk :

awk -v a='2,4,5,7' -v b='1,2,5,8' '
BEGIN { split(a, ax, ","); split(b, bx, ",");
        for(n in ax) mapping[ bx[n] ] =ax[n];
};
NR==FNR { if (FNR in mapping) hold[ mapping[FNR] ]=$0; next; };
{ print (FNR in hold)? hold[FNR]: $0; }' fileB fileA

Hier übergeben wir Zeilennummern als awk -v variabel in a='...' (für DateiA) und b='...' (für fileB), dann split() sie in ein Array mit Komma als Trennzeichen (beachten Sie, dass a und b waren Variablen, während jetzt ax und bx sind Arrays).

dann bauen wir ein weiteres mapping Array von ax und bx Arrays, um die Zeilen zuzuordnen, die in DateiA mit denen aus DateiB ersetzt werden sollen;

jetzt Schlüssel (oder Indizes) der mapping array sind Zeilennummern von fileB und die Werte dieser Schlüssel sind die Zeilennummern von fileA, wie unten:

die mapping Array ist:

Key    Value
1      2
2      4
5      5
8      7

Was wir also jetzt brauchen, ist, nur die Zeilennummern aus Datei B zu lesen, die mit den obigen Schlüsseln übereinstimmen (FNRs von 1 , 2 , 5 und 8 ), also machen wir das mit:

NR==FNR { if (FNR in mapping) hold[ mapping[FNR] ]=$0; next; };

OK, was ist nun der Wert von mapping[FNR] ? wenn Sie mapping überprüfen Array oben, das wäre:

mapping[1] --> 2; then-we-have    hold[ mapping[1] ] --> hold[2]=$0
mapping[2] --> 4; then-we-have    hold[ mapping[2] ] --> hold[4]=$0
mapping[5] --> 5; then-we-have    hold[ mapping[5] ] --> hold[5]=$0
mapping[8] --> 7; then-we-have    hold[ mapping[8] ] --> hold[7]=$0

also haben wir den Wert von mapping verwendet array als Schlüssel für hold Array und hold Das Array enthält jetzt:

Key     Value
2       Argentina
4       Switzerland
5       Denmark
7       Colombia

Jetzt ist der letzte Schritt, Schlüssel in hold zu verwenden array als übereinstimmende Zeilennummer in fileA und ersetzen Sie diese Zeilen durch die Werte dieses Schlüssels aus hold Array, wenn diese Zeilennummer im Array gefunden wird, oder drucke die Zeile selbst, wenn sie nicht gefunden wird (Ternärer Operator:condition? if-true : if-false ), und das machen wir mit:

{ print (FNR in hold)? hold[FNR]: $0; }

Unter Verwendung des Standard-sed :

$ printf '%ds/^/%dc\\\\\\\n/p\n' 1 2 2 4 5 5 8 7 | sed -n -f /dev/stdin fileB | sed -f /dev/stdin fileA
Italy
Argentina
USA
Switzerland
Denmark
Japan
Colombia

Die Befehlspipeline,

printf '%ds/^/%dc\\\\\\\n/p\n' 1 2 2 4 5 5 8 7 |
sed -n -f /dev/stdin fileB |
sed -f /dev/stdin fileA

erzeugt zuerst einen sed ersetzen Sie die Anweisung für jedes Zeilennummernpaar mit printf . Die Ausgabe von printf Aufruf ist folgender sed Skript:

1s/^/2c\\\
/p
2s/^/4c\\\
/p
5s/^/5c\\\
/p
8s/^/7c\\\
/p

Dieses sed Skript wirkt auf Zeile 1, 2, 5 und 8 und fügt nc\ ein gefolgt von einem wörtlichen Zeilenumbruch (für einige Zeilen mit der Nummer n ) am Anfang der betroffenen Zeilen.

Führen Sie dies über fileB aus (mit sed -n ) generiert einen neuen sed Skript:

2c\
Argentina
4c\
Switzerland
5c\
Denmark
7c\
Colombia

Der c Befehl ersetzt eine Zeile mit dem Text nach \ , also ersetzt das Skript die Zeilen 2, 4, 5 und 7.

Wenden Sie dies auf fileA an erzeugt das Ergebnis.

Lesen der Zeilennummern aus einer Datei, in der die erste Spalte Zeilennummern für fileB enthält , und die zweite Spalte enthält Zeilennummern für fileA :

$ cat number-pairs
1 2
2 4
5 5
8 7
$ awk '{ printf "%ds/^/%dc\\\\\\\n/p\n", $1, $2 }' number-pairs | sed -n -f /dev/stdin fileB | sed -f /dev/stdin fileA
Italy
Argentina
USA
Switzerland
Denmark
Japan
Colombia

Sie können natürlich $1 austauschen und $2 in er awk Ausdruck, wenn Sie die Spalten in umgekehrter Reihenfolge speichern möchten.


Linux
  1. Wie ersetze ich eine Zeichenfolge in einer oder mehreren Dateien?

  2. Ersetzen Sie eine Zeile durch einen anderen Inhalt mit Sed und Parallel für eine große Datei?

  3. Zeilenbereich durch Zeilenbereich ersetzen (sed oder andere)?

  4. Ersetzen Sie Linien, die einem Muster entsprechen, durch Linien aus einer anderen Datei in der richtigen Reihenfolge?

  5. Newline durch Nul ersetzen?

So entfernen Sie Zeilen aus einer Datei mit dem Sed-Befehl

Datei nach Anzahl der Zeilen aufteilen, einschließlich Header in jeder Zeile?

Löschen bestimmter Zeilen aus einer Datei in der Linux-Befehlszeile

Unix Sed Tutorial:Dateizeilen anhängen, einfügen, ersetzen und zählen

Wie ersetze ich eine Datei im JAR durch die Befehlszeile in Linux?

SED-Ersetzung über mehrere Zeilen hinweg