我需要比较两个文件中的数据,并根据需要更新 Shell 中的第二个文件的条件。
我有两组文件。
第一个文件包含的数据为
NUMBER,ID
748378,9508
473738,7892
473832,7839
第二个文件包含的数据为
pk,Name,Number,Code
1,Michael,748378,6373
2,Rachael,747477,7473
我想做的是更新第二个文件,就好像第二个文件中的 pk 不等于 1 并且第一个文件中的数字等于第二个文件中的数字,然后设置文件 2 中的代码 = 文件 1 中的 ID。
我在 shell 中处理这个逻辑时遇到了麻烦。
答案1
MS Excelvlookup
可以快速/轻松地解决此问题。
如果 Excel 不适合您,我会合并 awk/sed/shell:
awk -F, '{if ($1 != 1 && $1 ~ /[0-9]+/) {print "sed -i \x27s#" $3 ",[0-9]*#" $3 "," $4 "#\x27 file1.txt"}}' file2.txt | bash
就像马蒂亚斯提到的,如果我正确理解了初衷:
仅当 file2 中的 pk 不为 1 时,才将修复应用于 file1。
在这种情况下,您没有匹配项,因为 file2 中的“pk1 number748378”是 file1 中找到的唯一匹配项,并且当 pk 为 1 时您将排除修复。
在我提供的单行代码中,更改if ($1 != 1
为if ($1 != 2
以查看结果。
awk/sed/bash 合并的说明:
awk -F,
-F 表示使用后面的任何内容作为分隔符,在本例中,使用,
if ($1 != 1 && $1 ~ /[0-9]+/)
如果字段 1$1
不等于 1 并且如果字段 1 是数字,则应用以下 awk 过程。$1 ~ /reg_exp/
是awk
正则表达式语法。
print "sed -i \x27s#" $3 ",[0-9]*#" $3 "," $4 "#\x27 file1.txt"
用于awk
打印sed
命令以将修复应用到 file1.txt。 $3
是 NUMBER 是$4
是 file2.txt 中的代码。是打印的\x27
十六进制代码。awk
'
本质上,使用awk
查找 file2 中的字段 3 和 4 并使用sed
生成命令,将 file1 中的数字替换为 提供的结果awk
,然后sed
通过bash
(或您拥有的任何其他 shell)运行生成的命令
答案2
我想这就是你想要的脚本:
awk '
BEGIN { FS=OFS="," }
NR==FNR {
map[$1] = $2
next
}
($1 != 1) && ($3 in map) {
$4 = map[$3]
}
{ print }
' file1 file2
但示例输入中的任何行看起来都不符合您指定的条件,因此不会更改任何行,因此根据您提供的内容,无法对其进行测试。
答案3
以下 Perl 脚本可以完成您想要的操作:
#!/usr/bin/env perl
#
use strict;
use warnings;
my $file1 = shift;
my %ids_by_number;
if ($file1 && open(my $f1, "<", $file1)) {
my ($number,$id) = split(/,/,<$f1>);
while (<$f1>) {
my ($number,$id) = split(/,/);
$ids_by_number{$number} = $id;
}
}
else {
print "please provide file1 on the command line\n";
exit 1;
}
while (<>) {
my ($ok,$name,$number,$code) = split(/,/);
if ("1" ne $ok && exists($ids_by_number{$number})) {
print join(",",$ok,$name,$number,$ids_by_number{$number}),"\n";
}
else {
print $_;
}
}
不幸的是,您的示例不包含与我理解的条件相匹配的行。因此,我针对以下文件对其进行了测试:
pk,Name,Number,Code
1,Michael,748378,6373
2,Rachael,747477,7473
3,Raffael,473738,1234
您可以在命令行中使用两个文件名调用脚本:
$ ./update file1 file2
或者将 file2 提供给 STDIN:
$ ./update file1 file2
这两个调用都会在 STDOUT 上产生以下输出:
pk,Name,Number,Code
1,Michael,748378,6373
2,Rachael,747477,7473
3,Raffael,473738,7892