Utilizzando 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
Qui passiamo i numeri di riga come awk -v ariabile in a='...' (per fileA) e b='...' (per fileB), quindi split() in un array sul carattere virgola come separatore (nota che a e b erano variabili, mentre ora ax e bx sono array).
poi costruiamo un altro mapping matrice da ax e bx array per mappare le linee che devono essere sostituite nel fileA con quelle del fileB;
ora chiavi (o indici) del mapping array sono i numeri di riga del fileB e i valori di queste chiavi sono i numeri di riga del fileA, come di seguito:
il mapping matrice è:
Key Value
1 2
2 4
5 5
8 7
quindi ora ciò di cui abbiamo bisogno, cioè solo leggere i numeri di riga dal fileB che corrispondono alle chiavi sopra (FNR di 1 , 2 , 5 e 8 ), quindi lo facciamo con:
NR==FNR { if (FNR in mapping) hold[ mapping[FNR] ]=$0; next; };
OK, ora qual è il valore di mapping[FNR] ? se selezioni mapping array sopra, sarebbe:
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
quindi abbiamo utilizzato il valore di mapping array come chiave per hold matrice e hold l'array ora contiene:
Key Value
2 Argentina
4 Switzerland
5 Denmark
7 Colombia
ora l'ultimo passo è usare le chiavi in hold array come numero di riga corrispondente nel fileA e sostituisci quelle righe con i valori di quella chiave dal hold array se quel numero di riga è stato trovato nell'array o stampa la riga stessa se non è stata trovata (operatore ternario:condition? if-true : if-false ), e lo facciamo con:
{ print (FNR in hold)? hold[FNR]: $0; }
Utilizzando lo 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
La pipeline dei comandi,
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
prima genera un sed sostituire l'istruzione per ogni coppia di numeri di riga utilizzando printf . L'output di printf call è il seguente sed script:
1s/^/2c\\\
/p
2s/^/4c\\\
/p
5s/^/5c\\\
/p
8s/^/7c\\\
/p
Questo sed lo script agisce sulla riga 1, 2, 5 e 8 e inserisce nc\ seguito da una nuova riga letterale (per alcuni numeri di riga n ) all'inizio delle righe interessate.
Eseguendolo su fileB (con sed -n ) genera un nuovo sed script:
2c\
Argentina
4c\
Switzerland
5c\
Denmark
7c\
Colombia
Il c Il comando sostituisce una riga con il testo che segue il \ , quindi lo script sostituirà le righe 2, 4, 5 e 7.
Applicando questo a fileA genera il risultato.
Lettura dei numeri di riga da un file in cui la prima colonna contiene i numeri di riga per fileB e la seconda colonna contiene i numeri di riga per 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
Puoi ovviamente scambiare $1 e $2 in lui awk expression se desideri memorizzare le colonne nell'ordine opposto.