我有 2 个文件。
文件1:
123 pattern1
452 pattern2
601 pattern3
文件2:
12 a
34 b
88 ee
120 f
333 qw
400 oo
566 i
993 o
我想要的是从 file2 的第一列中找到与 file1 第一列中的每一行最接近的值,然后将相应的第二列添加到 file2 到 file1 (在新文件中)
这两个文件中都没有重复的值。
期望的输出:
123 pattern1 f
452 pattern2 oo
601 pattern3 i
我试图使用 awk,但它还远远没有工作:/
awk 'NR==FNR { seq[$2]=$1; next }
{
d = $1 - seq[$2];
d = d < 0 ? -d : d;
v = $1;
next
}
{
m = $1 - seq[$2];
m = m < 0 ? -m : m
}
m < d {
d = m;
v = $1
}
{ print $0 }' file1.txt file2.txt
答案1
博多已经指出您的代码存在问题并更正它们。我正在给出替代答案。
仅使用awk
。这是本质上与 Bodo 的答案相同,但它不会将第一个文件中的数据拆分为单独的数组。它也不使用神奇的数字常量(在其代码中为 -1)来初始化所看到的最小距离,而是使用以下事实:awk
当解释为字符串时,未设置的值是空的。
awk '
NR == FNR { num[$0] = $1; next }
{
for (a in num) {
d = (num[a]-$1)^2
if (min[a] == "" || d < min[a]) {
min[a] = d; symb[a] = $2
}
}
}
END { for (a in symb) print a, symb[a] }' file1 file2
其他方法:
join -1 3 -2 3 file1 file2 |
awk '{ print ($1-$3)^2, $0 }' |
sort -k 1,1n | sort -su -k 2,3 |
awk '{ print $2, $3, $5 }'
上面首先使用join
不存在的字段来创建所有输入数据的关系叉积(它将一个文件的每一行与另一个文件的所有行组合起来)。
该数据将如下所示:
123 pattern1 12 a
123 pattern1 34 b
[etc.]
601 pattern3 566 i
601 pattern3 993 o
然后,它计算距离度量并将其插入作为新的第一列:
12321 123 pattern1 12 a
7921 123 pattern1 34 b
[etc.]
1225 601 pattern3 566 i
153664 601 pattern3 993 o
这两个调用sort
首先根据距离度量对这些数据进行数字排序,然后使用第一个文件中的数据作为排序键并进行稳定的唯一排序。这将丢弃第一个文件中除第一个数据实例之外的所有数据,在本例中留下三行:
9 123 pattern1 120 f
2704 452 pattern2 400 oo
1225 601 pattern3 566 i
由此,我们挑选出我们感兴趣的列awk
:
123 pattern1 f
452 pattern2 oo
601 pattern3 i
答案2
您的脚本中有几个问题awk
。第二个动作块没有条件并以 结束next
。这就是为什么其他块永远不会被执行的原因。
使用第二个文件中的字段 2 作为索引seq
没有意义,因为字段 2 中的值在 file1 和 file2 之间不同。
awk 'NR==FNR {
seq[NR] = $1;
name[NR] = $2;
delta[NR] = -1;
count = NR;
next
}
{
for(i = 1; i <= count; i++) {
d = $1 - seq[i];
d = d < 0 ? -d : d;
if((delta[i] < 0) || (d < delta[i])) {
delta[i] = d;
val[i] = $2;
}
}
}
END {
for(i = 1; i <= count; i++) {
printf "%s %s\t%s\n", seq[i], name[i], val[i]
}
}' file1.txt file2.txt
印刷
123 pattern1 f
452 pattern2 oo
601 pattern3 i
答案3
如果更改文件的顺序,会更紧凑一些。
awk '
NR==FNR {A[$1]=$2; next}
{arg=1000
for(i in A){
cmp = sqrt(($1-i)^2)
if(cmp < arg)
{arg=cmp; third=A[i]}
}
print $0, third}
' file2 file1
表达式的部分sqrt(X^2)
执行绝对值的功能