Usando 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
Aquí, pasamos números de línea como un awk -v variable en a='...' (para el archivo A) y b='...' (para el archivo B), entonces split() en una matriz con carácter de coma como separador (tenga en cuenta que a y b eran variables, mientras que ahora ax y bx son matrices).
luego construimos otro mapping matriz de ax y bx arreglos para mapear las líneas que deben ser reemplazadas en el archivo A con las del archivo B;
ahora claves (o índices) del mapping matriz son los números de línea del archivo B y los valores de estas claves son los números de línea del archivo A, como se muestra a continuación:
el mapping matriz es:
Key Value
1 2
2 4
5 5
8 7
ahora lo que necesitamos, es decir, solo leer los números de línea del archivo B que coinciden con las claves anteriores (FNR de 1 , 2 , 5 y 8 ), así que hacemos eso con:
NR==FNR { if (FNR in mapping) hold[ mapping[FNR] ]=$0; next; };
Bien, ahora cuál es el valor del mapping[FNR] ? si marcas el mapping matriz anterior, sería:
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
así que usamos el valor de mapping matriz como clave para el hold matriz y hold la matriz ahora contiene:
Key Value
2 Argentina
4 Switzerland
5 Denmark
7 Colombia
ahora el último paso es usar claves en hold matriz como el número de línea coincidente en el archivo A y reemplace esas líneas con los valores de esa clave del hold matriz si ese número de línea se encuentra en la matriz o imprime la línea en sí misma si no se encuentra (operador ternario:condition? if-true : if-false ), y lo hacemos con:
{ print (FNR in hold)? hold[FNR]: $0; }
Usando sed estándar :
$ 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 canalización de comandos,
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
primero genera un sed declaración sustituta para cada par de números de línea usando printf . La salida del printf la llamada es la siguiente sed guión:
1s/^/2c\\\
/p
2s/^/4c\\\
/p
5s/^/5c\\\
/p
8s/^/7c\\\
/p
Este sed el script actúa en las líneas 1, 2, 5 y 8 e inserta nc\ seguido de una nueva línea literal (para algún número de línea n ) al comienzo de las líneas afectadas.
Ejecutando esto a través de fileB (con sed -n ) genera un nuevo sed guión:
2c\
Argentina
4c\
Switzerland
5c\
Denmark
7c\
Colombia
El c El comando reemplaza una línea con el texto que sigue al \ , por lo que la secuencia de comandos reemplazará las líneas 2, 4, 5 y 7.
Aplicando esto a fileA genera el resultado.
Leer los números de línea de un archivo en el que la primera columna contiene números de línea para fileB y la segunda columna contiene números de línea para 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
Obviamente puedes intercambiar $1 y $2 en él awk expresión si desea almacenar las columnas en el orden opuesto.