Заменить поле значениями, указанными в другом файле
У меня есть файл, который содержит карту между словами. Я должен обратиться к этому файлу и заменить эти слова на отображенные в некоторых файлах. Например, ниже файл имеет таблицу слов, которые отображаются как
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
У меня будет много файлов с этими ключевыми словами (1.12.2.*). Я хочу найти эти ключевые слова и заменить их соответствующими сопоставлениями, взятыми из этого файла. Как это сделать в оболочке. Предположим, что файл содержит следующие строки, скажем
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.
После выполнения сценария номера "1.12.2.12" и "1.12.2.4" должны быть заменены на 5 и 4 (по ссылке из основного файла). Может кто-нибудь мне помочь?
3 ответа
Один из способов использования GNU awk
:
awk 'FNR==NR { array[$1]=$2; next } { for (i in array) gsub(i, array[i]) }1' master.txt file.txt
Результаты:
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.
Чтобы сохранить вывод в файл:
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
Объяснение:
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'
Добавление границ слова делает соответствие более строгим:
awk 'FNR==NR { array[$1]=$2; next } { for (i in array) gsub("\\<"i"\\>", array[i]) }1' master.txt file.txt
Вы могли бы иметь sed
Напиши sed
скрипт для вас:
Отображения:
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
Входной файл:
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
Создайте сценарий на основе отображений (GNU sed):
sed -r -e 's:([^ ]*) +(.*):s/\\b\1\\b/\2/g:' mappings
Выход:
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
Оцените с другим sed
(GNU sed):
sed -r -e 's:([^ ]*) +(.*):s/\\b\1\\b/\2/g:' mappings | sed -f - infile
Выход:
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.
Обратите внимание, что сопоставления обрабатываются как регулярные выражения, например точка (.
) может означать любой символ и может потребоваться экранировать либо в файле сопоставлений, либо при генерации sed
скрипт.
Поскольку вы не предоставили ни одного примера, я думаю, это то, что вы хотите:
Входной файл
> 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
файл для передачи
> 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.
выход
> 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
>
Ниже приведен скрипт на Perl.
#!/usr/bin/perl
use strict;
use warnings;
my %hsh=();
open (MYFILE, 'temp');
open (MYFILE2, 'temp2');
while (<MYFILE>) {
my@arr = split/\s+/;
$hsh{$arr[0]} = $arr[1];
}
my $flag;
while(<MYFILE2>)
{
$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);