Pomocí 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
Zde předáváme čísla řádků jako awk -v
ariable v a='...'
(pro soubor A) a b='...'
(pro soubor B), pak jsme split()
do pole se znakem čárky jako oddělovačem (všimněte si, že a
a b
byly proměnné, zatímco nyní ax
a bx
jsou pole).
pak vytvoříme další mapping
pole z ax
a bx
pole k mapování řádků, které by měly být nahrazeny v souboru A řádky ze souboru B;
nyní klíče (nebo indexy) mapping
pole jsou čísla řádků souboruB a hodnoty těchto klíčů jsou čísla řádků souboruA, jak je uvedeno níže:
mapping
pole je:
Key Value
1 2
2 4
5 5
8 7
takže teď to, co potřebujeme, tedy jen přečíst čísla řádků ze souboru B, která odpovídají výše uvedeným klíčům (FNR 1
, 2
, 5
a 8
), takže to uděláme pomocí:
NR==FNR { if (FNR in mapping) hold[ mapping[FNR] ]=$0; next; };
OK, teď jaká je hodnota mapping[FNR]
? pokud zaškrtnete mapping
pole výše, to by bylo:
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
takže jsme použili hodnotu mapping
pole jako klíč pro hold
pole a hold
pole nyní obsahuje:
Key Value
2 Argentina
4 Switzerland
5 Denmark
7 Colombia
nyní posledním krokem je použití klíčů v hold
pole jako odpovídající číslo řádku v souboru A a nahraďte tyto řádky hodnotami tohoto klíče z hold
pole, pokud je toto číslo řádku nalezeno v poli, nebo vytiskněte samotný řádek, pokud nebylo nalezeno (ternární operátor:condition? if-true : if-false
), a to pomocí:
{ print (FNR in hold)? hold[FNR]: $0; }
Pomocí standardního 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
Příkazový kanál,
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
nejprve vygeneruje sed
nahradit příkaz pro každý pár čísel řádků pomocí printf
. Výstup printf
volání je následující sed
skript:
1s/^/2c\\\
/p
2s/^/4c\\\
/p
5s/^/5c\\\
/p
8s/^/7c\\\
/p
Toto sed
skript funguje na řádku 1, 2, 5 a 8 a vloží nc\
následovaný doslovným novým řádkem (pro některé číslo řádku n
) na začátku dotčených řádků.
Spuštění přes fileB
(s sed -n
) vygeneruje nový sed
skript:
2c\
Argentina
4c\
Switzerland
5c\
Denmark
7c\
Colombia
c
příkaz nahradí řádek textem následujícím za \
, takže skript nahradí řádky 2, 4, 5 a 7.
Toto použijete na fileA
vygeneruje výsledek.
Čtení čísel řádků ze souboru, ve kterém první sloupec obsahuje čísla řádků pro fileB
a druhý sloupec obsahuje čísla řádků pro 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
Samozřejmě můžete vyměnit $1
a $2
v awk
výraz, pokud chcete ukládat sloupce v opačném pořadí.