使用 awk + ​​if 语句比较两列中行的所有组合

使用 awk + ​​if 语句比较两列中行的所有组合

我有一个包含 11 列数据的文件,每列之间用空格分隔。对于第 2 列中的每一行,我需要在第 9 列中找到最接近的值。因此,下面将采用第 2 列中的第一个条目 (0.01) 并在第 9 列中找到最接近的值(第 3 行中的 0.009)。

文件布局:

x 0.01 x x x x x x 0.002 x x
x 0.034 x x x x x x 0.0045 x x
x 0.002 x x x x x x 0.009 z z
x 0.002 x x x x x x 0.0021 x x
x 0.015 x x x x x x 0.0031 x x

当前代码:

awk '{
if (sqrt(($2)^2-($9)^2)<0.0001)
   print "Particle ID  "$1" is within 2D of wall"
}' filename

我认为这有两个问题:

1)这并不比较每个排列,只是比较列中的每一行

2)它只检查它们是否在某个范围内,而不是最接近的。

所需的输出将是一个新文件,类似于

x 0.01 x x x x x x 0.009 z z

对于所有其他线路依此类推

答案1

使用awkTXR 口齿不清:

$ txr closest.tl < data
x 0.01 x x x x x x 0.009 x x
x 0.034 x x x x x x 0.009 x x
x 0.002 x x x x x x 0.0021 z z
x 0.002 x x x x x x 0.0021 x x
x 0.015 x x x x x x 0.009 x x

代码在closest.tl

(build
  (awk
    ((fconv - r : : r - -) (add f))
    (:end (let ((fs (get)))
            (each ((f fs))
              (let ((min (find-min fs : (op abs (- [f 1] [@1 8])))))
                (set [f 8] [min 8])
                (prn . f)))))))

  • build创建一个用于按程序构造隐式列表的环境。在 包含的代码中build,我们用于(add ...)将项目添加到隐式列表并(get)检索该列表。

  • 在环境内部build,我们有一个宏的实例awk。该宏具有一条条件动作规则和一条:end规则。在条件-动作规则中,我们有一个(fconv ...)表达式作为条件。这是无条件正确的,因此我们匹配每条记录。将fconv选定字段转换为浮点(r=“实数”)。该操作的意思是(add f):将当前字段列表添加到隐式列表中。因此,我们将数据构建为行列表,即字段列表。

    fconv之所以需要,是因为 TXR Lisp 是一种强类型语言。该awk宏实现了 Awk 的许多语义,但没有实现我们可以将字符串视为"3.14"数字的鸭子类型。

  • 当数据结束时,:end子句触发awk,这就是我们进行最近距离处理的地方。我们将行放入一个名为 的变量中,并为每行fs迭代一个变量。f对于每一行,我们从 中找到最小项fs,其中该项是所检查的每一行中该行的字段 1 和字段 8 之间的差的绝对值。当我们找到最小距离行时,我们将该行的字段 8 替换为该最小距离行的字段 8。

    请注意,字段从 0 开始编号:[f 0], [f 1], ... 与 Awk 不同,没有约定零字段是整个记录;整个记录称为rec.

  • 将字段替换[f 8]为最小距离字段后,我们打印字段。

相关内容