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
,然后删除临时文件。