Awk:如果数值接近,则匹配2个文件中的列值

时间:2014-04-08 11:48:54

标签: bash awk

在这里提出我的第一个问题(Awk: Length of column number

我的数据:

档案1

8.193506084253E+06 1.900521460E+01
8.193538509494E+06 1.899919490E+01
8.193540934736E+06 1.899317535E+01
8.193543359977E+06 1.898720476E+01
8.193546406105E+06 1.897934066E+01

文件2

8.193505938557E+06 1.572155163E+01
8.193509618041E+06 1.573016361E+01 
8.193513297526E+06 1.573874442E+01 
8.193516977010E+06 1.574725969E+01

我想从文件2中取1美元并在文件1中搜索$ 1中最接近的*值,以获得类似此示例的输出

 8.193505938557E+06 1.572155163E+01 1.900521460E+01

在这种情况下,文件2中列$ 1的唯一第一个值匹配,没有其他因为文件2中$ 1的其他值与文件1中的任何值$ 1不够接近(定义某些条件)

请注意,行数不同 * nearest =两个数字之间的差异小于某个阈值

2 个答案:

答案 0 :(得分:3)

据我了解,根据你的描述,结果应该是:

1235.34 d a
3457.23 e b
7589.34 f b

即。包括" f"最接近" b"。

这可以使用以下脚本完成:

ARGIND == 1 {
    haystack[$1] = $2;
}
ARGIND == 2 {
    bestdiff=-1;
    for (v in haystack)
        if (bestdiff < 0 || (v-$1)**2 < bestdiff) {
            bestkey=haystack[v];
            bestdiff=(v-$1)**2;
        }
    print $1, $2, bestkey;
}

(我通过**2使用平方代替取绝对值。)

如果要在差异大于10时抑制结果,要获得引用的结果,请使用以下内容:

if (bestdiff < 10**2)
    print $1, $2, bestkey;

编辑:OP更改了问题中的示例输入和输出。以下是原始示例文件供参考。文件1:

1234.34  a 
3456.23  b 
2325.89  c 
2326.20  c2

文件2:

1235.34 d
3457.23 e
7589.34 f

输出:

1235.34 d a
3457.23 e b

注意: ARGIND**是GNU扩展。有关详细信息,请参阅下面mklement0的评论。

答案 1 :(得分:1)

将第一列值加载到file2的数组中。 然后使用abs函数比较差异。 该脚本将输出最接近的匹配(最接近意味着单个最高级别)。

awk 'BEGIN{closestVal=9999}
     function abs(x){return ((x < 0.0) ? -x : x)} 

     {
      if (NR==FNR) { f1col2[NR]=$2;v[NR]=$1; next; }

      for (n in v)
      {
        if (abs(v[n] - $1) < closestVal)
        {
            closestVal = abs(v[n] - $1)
            closestLine = $0 " " f1col2[n]
        }
    }
 }   
END {print closestLine}' file1 file2