Замените поле на значения, указанные в другом файле

У меня есть файл, содержащий карту между словами. Я должен обратиться к этому файлу и заменить эти слова на сопоставленные в некоторых файлах. Например, ниже в файле есть таблица слов, которые отображаются как

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.

После выполнения script номера "1.12.2.12" и "1.12.2.4" должны быть заменены на 5 и 4 (см. основной файл). Может ли кто-нибудь помочь мне?

Ответы

Ответ 1

Один из способов: 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 "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 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

Ответ 2

У вас может быть sed написать sed script для вас:

Отображения:

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

Создать script на основе сопоставлений (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 script.

Ответ 3

Поскольку вы не предоставили какой-либо пример, я думаю, это то, что вы хотите:

Входной файл

> 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 script.

#!/usr/bin/perl

use strict;
use warnings;

my %hsh=();

open (MYFILE, 'temp');
open (MYFILE2, 'temp2');

while (<MYFILE>) {
[email protected] = 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);