标题可能令人困惑,这就是我想要做的:
File1 12=921:5,895:5,813:5,853:5,978:5,807:5,1200:5,1067:5,827:5 File2 Tom 12 John 921 Mike 813 Output Tom=John:5,Mike:5
file2 具有 file1 中数字的值,我想用字符串值匹配和替换数字。我在 awk 知识有限的情况下尝试了这个,但做不到。
任何帮助表示赞赏。
这是使用GNU awk
. 像这样运行:
awk -f script.awk file1 file2
内容script.awk
:
BEGIN {
FS="[ =:,]"
}
FNR==NR {
a[$1]=$0
next
}
$2 in a {
split(a[$2],b)
for (i=3;i<=NF-1;i+=2) {
for (j=2;j<=length(b)-1;j+=2) {
if ($(i+1) == b[j]) {
line = (line ? line "," : "") $i ":" b[j+1]
}
}
}
print $1 "=" line
line = ""
}
结果:
Tom=John:5,Mike:5
或者,这是单线:
awk -F "[ =:,]" 'FNR==NR { a[$1]=$0; next } $2 in a { split(a[$2],b); for (i=3;i<=NF-1;i+=2) for (j=2;j<=length(b)-1;j+=2) if ($(i+1) == b[j]) line = (line ? line "," : "") $i ":" b[j+1]; print $1 "=" line; line = "" }' file1 file2
解释:
将 awk 的字段分隔符更改为空格、等号、冒号或逗号。
'FNR==NR { ... }' 仅适用于参数列表中的第一个文件。
因此,在处理 file1 时,awk 会将列 '1' 添加到数组中,并将整行作为值分配给该数组元素。
'next' 将简单地跳过处理脚本的其余部分,并读取下一行输入。
当 awk 读完 file1 中的输入后,它会继续读 file2。但是,这也会将“FNR”重置为“1”,因此 awk 将跳过处理 file2 的“FNR==NR”块,因为它不再为真。
所以对于file2:如果可以在上面提到的数组中找到列'2':
将数组元素的值拆分为另一个数组。这实质上拆分了 file1 中的整行。
现在创建两个循环。
第一个将遍历 file2 中的所有名称
第二个将遍历(第二个)数组中的所有值(这实际上是遍历 file1 中的所有字段)。
现在,当 file2 中的名称后面的值等于 file1 中的键号之一时,创建一个类似于:'name:number_following_key_number_from_file1'的行结构。
当在循环中找到更多名称和值时,四元构造 '( ... ? ... : ...)' 将这些元素添加到行尾。这就像一个 if 语句;如果已经有一行,则在其末尾添加一个逗号,否则不执行任何操作。
完成所有循环后,打印出列“1”和行。然后清空行变量,以便它可以再次使用。
HTH。祝你好运。
以下可以作为模板:
skrynesaver@busybox ~/ perl -e '$values="12=921:5,895:5,813:5,853:5,978:5,807:5,1200:5,1067:5,827:5";
$data = "Tom 12 John 921 Mike 813";
($line,$values)=split/=/,$values;
@values=split/,/,$values;
$values{$line}="=";
map{$_=~/(\d+)(:\d+)/;$values{$1}="$2";}@values;
if ($data=~/\w+\s$line\s/){
$data=~s/(\w+)\s(\d+)\s?/$1$values{$2}/g;
}
print "$data\n";
'
Tom=John:5Mike:5
skrynesaver@busybox ~/