【问题标题】:Have a file filtered by each column accordingly with a range of values from another columns file有一个文件相应地按每一列过滤,其中包含来自另一个列文件的一系列值
【发布时间】:2015-08-26 00:19:44
【问题描述】:

我希望有一种方法可以将一个文件相应地过滤到另一个文件,但要考虑每个文件的不同范围,因为数量不同并且第 1 列的名称也不同。因此,例如,第 2 列和第 4 列可以在 50 的范围内变化,而第 3 列和第 5 列分别为 0.05 和 0.005。

文件 1

ddd 10  2   0.3 4   0.02
ccc 250 22  0.2 2   0.04
aaa 10  10  0.10    10  0.02
xxx 12  12  0.12    2   0.01
showman 150 15  0.15    200 0.003
porco   15  100 0.15    15  12

文件 2

super   120 11  0.12    150 0.005

输出

showman 150 15  0.15    200 0.003

【问题讨论】:

  • 到目前为止您尝试过什么?这是否与文件 2 的许多不同版本有关和/或每列的容差范围会有所不同?
  • 如果文件 2 只有几个不同版本,我建议直接将其编写为以 file 1 为输入的 awk 脚本。如果file 2 可能有许多不同的版本,解决此问题的一种方法是编写一个awk 脚​​本,该脚本将file 2 作为输入并生成一个脚本file2.awk,该脚本在提供@987654330 时执行过滤@.
  • 我尝试了一些 awk 命令,但问题是我不知道如何为一个文件的每一列创建一个变量并使用这些变量来创建一个范围并在其他文件中搜索值

标签: awk filter range multiple-columns two-columns


【解决方案1】:

这类似于 Simon 的解决方案,但它避免了两次调用 awk。

function abs(x) {return ((x < 0.0) ? -x : x)}

BEGIN {
    tol[2]=50
    tol[3]=5
    tol[4]=0.05
    tol[5]=50
    tol[6]=0.005
}

FNR==NR {
    for (i=2; i<=NF; i++)
       target[i]=$i
}

FNR < NR {
    for (i=2; i<=NF; i++)
        if (abs($i - target[i]) > tol[i])
            next
    print
}

使用awk -f match.awk file2 file1拨打电话

【讨论】:

    【解决方案2】:

    以下 shell 脚本(我称为 filterrange)从 file2.txt 生成 awk 脚本 filterrange.awk,然后运行该 awk 脚本进行过滤:

    #!/bin/sh
    awk 'BEGIN { r[2] = 50; r[3] = 5; r[4] = 0.05; r[5] = 50; r[6] = 0.005 }
           { print "function abs(x){return ((x < 0.0) ? -x : x)}"
             for (i = 2; i <= NF; i++) {
               printf("abs($%s-%s)<=%s", i, $i, r[i])
               if (i < NF) printf(" && ")
               } 
           }' <$1 >filterrange.awk
    awk -f filterrange.awk <$2
    

    abs() 函数来自Absolute value in awk doesn't work?

    运行这个 shell 脚本会得到以下结果:

    $ filterrange file2.txt file1.txt
    showman 150 15  0.15    200 0.003
    

    范围公差在此处显示的模板awk 脚本中是固定的,但如果需要,可以使用类似的方法从单独的文件轻松生成它们。

    【讨论】:

    • 出了点问题=\我唯一得到的是:bash filterrange compare.txt permut1.txt awk: syntax error at source line 2 source file filterrange.awk context is abs($2-120)&lt;=50 &amp;&amp; abs($3-11)&lt;=5 &amp;&amp; abs($4-0.12)&lt;=0,05 &amp;&amp; abs($5-150)&lt;=50 &amp;&amp; &gt;&gt;&gt; abs($6-0.005)&lt;=0, &lt;&lt;&lt; awk: bailing out at source line 2
    • 你的脚本在我朋友的机器上运行,但不在我的机器上,而@chthonicdaemon 的命令在我的机器上运行,而不是在他的机器上运行。
    • 语法错误是由于file2.txt 中的第六列是0,005(带逗号),而它应该是0.005(带句点)。 @chthonicdaemon 的答案更简单,所以我推荐它而不是我的,但在某些情况下,我的解决方案可以运行得更快。我必须进行基准测试才能确定。无论如何,在寻求快速解决方案之前,最好有一个可行的解决方案。
    • 我发现问题在于我在 MAC 上的语言选项会自动更改 filterrange.awk 的输出为逗号。我只需要将计算机的语言选项更改为英语,然后您的命令行就可以完美运行;)谢谢@Simon!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-21
    • 1970-01-01
    • 2020-03-24
    • 2022-01-24
    • 1970-01-01
    • 2021-09-12
    相关资源
    最近更新 更多