Utilisation de 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
Ici, nous passons les numéros de ligne comme un awk -v
variable en a='...'
(pour fichierA) et b='...'
(pour fileB), alors on split()
les dans un tableau sur le caractère virgule comme séparateur (notez que a
et b
étaient des variables, alors que maintenant ax
et bx
sont des tableaux).
puis on construit un autre mapping
tableau de ax
et bx
tableaux pour mapper les lignes qui doivent être remplacées dans le fichier A avec celles du fichier B ;
maintenant les clés (ou index) du mapping
array est les numéros de ligne du fichier B et les valeurs de ces clés sont les numéros de ligne du fichier A, comme ci-dessous :
le mapping
tableau est :
Key Value
1 2
2 4
5 5
8 7
alors maintenant, ce dont nous avons besoin, c'est-à-dire simplement lire les numéros de ligne du fichier B qui correspondent aux clés ci-dessus (FNR de 1
, 2
, 5
et 8
), donc on fait ça avec :
NR==FNR { if (FNR in mapping) hold[ mapping[FNR] ]=$0; next; };
OK, maintenant quelle est la valeur du mapping[FNR]
? si vous cochez le mapping
tableau ci-dessus, ce serait :
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
nous avons donc utilisé la valeur de mapping
tableau comme clé pour le hold
tableau et hold
tableau contient maintenant :
Key Value
2 Argentina
4 Switzerland
5 Denmark
7 Colombia
maintenant la dernière étape consiste à utiliser les clés en hold
tableau comme numéro de ligne correspondant dans le fichierA et remplacez ces lignes par les valeurs de cette clé à partir du hold
tableau si ce numéro de ligne se trouve dans le tableau ou imprime la ligne elle-même si elle n'est pas trouvée (opérateur ternaire :condition? if-true : if-false
), et nous le faisons avec :
{ print (FNR in hold)? hold[FNR]: $0; }
Utilisation de la norme 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
Le pipeline de commandes,
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
génère d'abord un sed
instruction de substitution pour chaque paire de numéros de ligne en utilisant printf
. La sortie du printf
l'appel est le suivant sed
script :
1s/^/2c\\\
/p
2s/^/4c\\\
/p
5s/^/5c\\\
/p
8s/^/7c\\\
/p
Ce sed
le script agit sur les lignes 1, 2, 5 et 8 et insère nc\
suivi d'un retour à la ligne littéral (pour certains numéros de ligne n
) au début des lignes concernées.
Exécuter ceci sur fileB
(avec sed -n
) génère un nouveau sed
script :
2c\
Argentina
4c\
Switzerland
5c\
Denmark
7c\
Colombia
Le c
La commande remplace une ligne par le texte suivant le \
, le script remplacera donc les lignes 2, 4, 5 et 7.
Appliquer ceci à fileA
génère le résultat.
Lecture des numéros de ligne d'un fichier dans lequel la première colonne contient des numéros de ligne pour fileB
, et la deuxième colonne contient les numéros de ligne pour 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
Vous pouvez évidemment échanger $1
et $2
dans le awk
expression si vous souhaitez stocker les colonnes dans l'ordre inverse.