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.