Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/shell/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Shell 用另一个文件中指定的值替换字段_Shell_Sed_Awk - Fatal编程技术网

Shell 用另一个文件中指定的值替换字段

Shell 用另一个文件中指定的值替换字段,shell,sed,awk,Shell,Sed,Awk,我有一个包含单词之间映射的文件。我必须参考该文件,并用一些文件中的映射词替换这些词。例如,下面的文件有一个单词表,映射如下 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.*)。我想搜索这些关键字

我有一个包含单词之间映射的文件。我必须参考该文件,并用一些文件中的映射词替换这些词。例如,下面的文件有一个单词表,映射如下

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.*)。我想搜索这些关键字,并用从此文件中获取的相应映射替换这些关键字。如何在shell中执行此操作。假设一个文件包含以下行

客户的Id为1.12.2.12。他来自Grg。
机器的名称是ASB
id为1.12.2.4。他来自巴黎圣日耳曼。

执行脚本后,数字“1.12.2.12”和“1.12.2.4”应替换为5和4(参考主文件)。有人能帮我吗?

既然你没有提供任何例子,我想这就是你想要的:

输入文件

> 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);
#/usr/bin/perl
严格使用;
使用警告;
我的%hsh=();
打开(MYFILE,'temp');
打开(MYFILE2,“temp2”);
而(){
my@arr=拆分/\s+/;
$hsh{$arr[0]}=$arr[1];
}
我的$flag;
while()
{
$flag=0;
我的$line=$\ux;
foreach my$密钥(密钥%hsh)
{
如果($line=~/$key/)
{
$flag=1;
$line=~s/$key/$hsh{$key}/g;
打印$行;
}
}
如果($flag!=1)
{
打印$行;
$flag=0;
}
}
关闭(MYFILE);
关闭(MYFILE2);

单向使用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
说明:

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
添加单词边界使匹配更加严格:

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
awk'FNR==NR{array[$1]=$2;next}{for(数组中的i)gsub(“\\”,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
输出:

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)进行评估:

输出:

客户的Id是5。他来自Grg。
机器的名称是ASB
id是1。他来自巴黎圣日耳曼。

请注意,映射被视为正则表达式,例如点(
)可以表示任何字符,可能需要在映射文件中或在生成
sed
脚本时转义。

显然,如果
master.txt
中的键太相似,这将中断。。我希望将这些值写入文件中。我该怎么做?我是shell脚本的新手。对不起的:(…提前感谢..实际上gsub会替换,即使部分行匹配..比如假设映射文件包含10.1.1.12 1这样的条目,并且我需要更改的文件有两个条目,例如.10.1.1.12和10.1.1.1234,那么这会替换两行..如何消除?@steve:我错过了第一个块中的
下一个
,所以忽略我之前的评论。@user1667630:要只匹配整个单词,您可以在匹配时添加单词边界,例如:
gsub(\\”,array[i])
;最好只让第一个匹配生效:`if(gsub(\\”,array[i])中断;@Thor:谢谢您的建议。我不知道这个语法:-)这不起作用..我在执行..sed:-e expression#1,char 26:s命令的RHSForgot上的引用无效\2,我已将sed
化名为
sed-r
。我已将
-r
添加到相关的表达式中。我仍然得到错误..sed:file-第1行:未知命令:`.!!我想有什么地方出错了..@user1667630:您使用的是哪个版本的sed?我刚刚用FreeBSD sed测试了这个版本,如果您将
-f-
替换为
-f/dev/stdin
,它可以工作。正如其他地方提到的,匹配关键字的单词边界是一个好主意,所以我添加了它,但现在生成的表达式不起作用。我认为您应该尝试使用GNU sed如果可以,通常称为gsed,它会提供更多选项。在最坏的情况下,将生成的脚本保存到临时文件中,运行
sed-f/tmp/temporary.sed
,然后删除临时文件。