根据 2 个字段的过滤条件选择所有记录

根据 2 个字段的过滤条件选择所有记录
ABC,1234.5333,5733.9374,5673.352,352,2.346374,-0.6686874
XYZ,5463.674,93773.683,5734.874,432,-5.683423,-10.38393
AES,7436874.5743,937.6843,8464.5634,564,6.35739,10.6834
PQR,784945.464,57484.8647,57484.453,5764,-10.67484,5.74764

从上面的 csv 文件中,我需要编写 shell 脚本,该脚本将选择最后两个字段 [ ABS(第 6 个字段)或 ABS(第 7 个字段)] 中任何一个的绝对值 > = 10 的所有记录。

结果,我的输出应该如下所示:

XYZ,5463.674,93773.683,5734.874,432,-5.683423,-10.38393
AES,7436874.5743,937.6843,8464.5634,564,6.35739,10.6834
PQR,784945.464,57484.8647,57484.453,5764,-10.67484,5.74764

答案1

正如您所暗示的,您可以使用 awk 来实现此目的。您需要定义自己的函数来获取绝对值。所以你可以使用这样的东西:

awk -F, 'function abs(a) {return a < 0 ? -a : a};(abs($6) >= 10 || abs($7) >= 10)' inputfile.txt 
XYZ,5463.674,93773.683,5734.874,432,-5.683423,-10.38393
AES,7436874.5743,937.6843,8464.5634,564,6.35739,10.6834
PQR,784945.464,57484.8647,57484.453,5764,-10.67484,5.74764

答案2

您可以尝试使用awk.类似的东西可以完成这项工作(仅使用内部函数):

awk -F\, '{if (sqrt($(NF-1)*$(NF-1))>=10 || sqrt($NF*$NF)>=10 ) { print $0}}'  input_file

答案3

csv使用可以解析数据和过滤行的工具,例如python使用csvmodule 或csvsqlfrom csvkit

csvsql -H --query 'select * from file where abs(f) > 10 or abs(g) > 10' file | sed 1d

(我通过管道sed删除输出标题行)。

输出:

XYZ,5463.674,93773.683,5734.874,432.0,-5.683423,-10.38393
AES,7436874.5743,937.6843,8464.5634,564.0,6.35739,10.6834
PQR,784945.464,57484.8647,57484.453,5764.0,-10.67484,5.74764

答案4

使用 Miller ( mlr) 及其filter子命令从无标头 CSV 文件中过滤(提取)倒数第二个或最后一个字段的大小为 10 或更大的每条记录:

$ mlr --csv -N filter 'abs($[NF-1]) >= 10 || abs($[NF]) >= 10' file
XYZ,5463.674,93773.683,5734.874,432,-5.683423,-10.38393
AES,7436874.5743,937.6843,8464.5634,564,6.35739,10.6834
PQR,784945.464,57484.8647,57484.453,5764,-10.67484,5.74764

如 中awkNF是当前记录中的字段数。 with$[NF]我们得到最后一个字段的值,而 while$[NF-1]给我们倒数第二个字段的值。

如果数据有标题,则可以删除该-N选项并使用字段名称代替等$[NF],例如

mlr --csv filter 'abs($fieldA) >= 10 || abs($fieldB) >= 10' file

相关内容