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.