Sostituisci un campo con valori specificati in un altro file

Ho un file che contiene la mappa tra le parole. Devo fare riferimento a quel file e sostituire quelle parole con quelle mappate in alcuni file. Ad esempio, sotto il file ha la tabella delle parole che sono mappate come

1.12.2.4 1 1.12.2.7 12 1.12.2.2 5 1.12.2.4 4 1.12.2.6 67 1.12.2.12 5 

Avrò molti file con quelle parole chiave (1.12.2. *). Voglio cercare queste parole chiave e sostituire quelle parole con la mapping corrispondente presa da questo file. Come farlo in shell. Supponiamo che un file contenga le seguenti righe

 The Id of the customer is 1.12.2.12. He is from Grg. The Name of the machine is ASB The id is 1.12.2.4. He is from Psg. 

Dopo aver eseguito lo script, i numeri “1.12.2.12” e “1.12.2.4” devono essere sostituiti da 5 e 4 (riferiti dal file principale). Qualcuno mi può aiutare?

Un modo con GNU awk :

 awk 'FNR==NR { array[$1]=$2; next } { for (i in array) gsub(i, array[i]) }1' master.txt file.txt 

risultati:

 The Id of the customer is 5. He is from Grg. The Name of the machine is ASB The id is 4. He is from Psg. 

Per salvare l’output in un file:

 awk 'FNR==NR { array[$1]=$2; next } { for (i in array) gsub(i, array[i]) }1' master.txt file.txt > name_of_your_output_file.txt 

Spiegazione:

 FNR==NR { ... } # FNR is the current record number, NR is the record number # so FNR==NR simply means: "while we process the first file listed # in this case it's "master.txt" array[$1]=$2 # add column 1 to an array with a value of column 2 next # go onto the next record { # this could be written as: FNR!=NR # so this means "while we process the second file listed..." for (i in array) # means "for every element/key in the array..." gsub(i, array[i]) # perform a global substitution on each line replacing the key # with it's value if found }1 # this is shorthand for 'print' 

L’aggiunta di limiti di parole rende la corrispondenza più rigorosa:

 awk 'FNR==NR { array[$1]=$2; next } { for (i in array) gsub("\\<"i"\\>", array[i]) }1' master.txt file.txt 

Potresti scrivere sed uno script per te:

Le mappature:

 cat << EOF > mappings 1.12.2.4 1 1.12.2.7 12 1.12.2.2 5 1.12.2.4 4 1.12.2.6 67 1.12.2.12 5 EOF 

File di input:

 cat << EOF > infile The Id of the customer is 1.12.2.12. He is from Grg. The Name of the machine is ASB The id is 1.12.2.4. He is from Psg. EOF 

Genera uno script basato sui mapping (GNU sed):

 sed -r -e 's:([^ ]*) +(.*):s/\\b\1\\b/\2/g:' mappings 

Produzione:

 s/\b1.12.2.4\b/1/g s/\b1.12.2.7\b/12/g s/\b1.12.2.2\b/5/g s/\b1.12.2.4\b/4/g s/\b1.12.2.6\b/67/g s/\b1.12.2.12\b/5/g 

Valutare con un altro sed (GNU sed):

 sed -r -e 's:([^ ]*) +(.*):s/\\b\1\\b/\2/g:' mappings | sed -f - infile 

Produzione:

 The Id of the customer is 5. He is from Grg. The Name of the machine is ASB The id is 1. He is from Psg. 

Si noti che le mappature sono trattate come espressioni regolari, ad esempio un punto ( . ) Può significare qualsiasi carattere, e potrebbe essere necessario eseguire l’escape sia nel file di mapping o quando si genera lo script sed .

Dato che non hai fornito alcun esempio, immagino che questo sia quello che vuoi:

File di input

 > cat temp 1.12.2.4 1 1.12.2.7 12 1.12.2.2 5 1.12.2.4 4 1.12.2.6 67 1.12.2.12 5 

file da relazionare

 > cat temp2 The Id of the customer is 1.12.2.12. He is from Grg. The Name of the machine is ASB The id is 1.12.2.4. He is from Psg. 

produzione

 > temp.pl The Id of the customer is 5. He is from Grg. The Name of the machine is ASB The id is 4. He is from Psg > 

Di seguito è riportato lo script perl.

 #!/usr/bin/perl use strict; use warnings; my %hsh=(); open (MYFILE, 'temp'); open (MYFILE2, 'temp2'); while () { [email protected] = split/\s+/; $hsh{$arr[0]} = $arr[1]; } my $flag; while() { $flag=0; my $line=$_; foreach my $key (keys %hsh) { if($line=~/$key/) { $flag=1; $line=~s/$key/$hsh{$key}/g; print $line; } } if($flag!=1) { print $line; $flag=0; } } close(MYFILE); close(MYFILE2);