【问题标题】:Awk compare 2 files and match 2 columns, get % difference between column 3sawk比较2个文件并匹配2列,得到第3列之间的百分比差异
【发布时间】:2020-05-13 02:55:39
【问题描述】:

我有 2 个文件,格式如下。我正在尝试比较第 1 列和第 2 列匹配的行,然后获取第 3 列中 2 # 的差异。

如果文件 2 的第 3 列大于文件 1 的第 3 列,我想在行尾加一个 +
如果 file2 列小于文件 1 第 3 列,我想在行尾添加 -
如果任一文件第 3 列为 0,我希望在行尾添加 *。

我只想打印两列之间差异大于 15% 的行

文件1

abc,1,472
abc,2,536
abc,3,652
abc,4,512
abc,5,474
abc,6,266
abc,7,520
def,1,954
def,9,538
def,10,136
def,11,341
def,12,183
def,13,1209
def,14,365
def,15,536
def,16,979
def,17,0
xyz,1,547
xyz,19,0
xyz,20,0
xyz,21,0
xyz,22,0
xyz,23,0
xyz,24,0

文件 2

abc,1,456
abc,2,533
abc,3,643
abc,4,444
abc,5,124
abc,6,255
abc,7,520
def,1,954
def,9,538
def,10,435
def,11,341
def,12,155
def,13,1209
def,14,365
def,15,536
def,16,979
def,17,0
xyz,1,547
xyz,19,124
xyz,20,0
xyz,21,0
xyz,22,0
xyz,23,0
xyz,24,0

预期输出

abc,5,474,124,74%,-     // (474-124)/474 = 74%
def,10,136,435,31%,+.   // (435-136)/474 = 69%
xyz,19,0,124,100%,*.    // either file has 0 , print 100% and *

我已经尝试过多次迭代,但似乎无法使格式正常工作。

  awk -F, 'FNR==NR{a[$1,$2]; next ;b[$1,$2,$3]; next} $1,$2 in a {if ($3>b[$3]) {Q=((b[$3]/$3) *100)) {print Q,$0 }} else if (b[$3]>$3) {Q=(($3/b[$3]) *100)){print Q,$0 }}' file1 file2

我收到此错误
^ 意外的换行符或字符串结尾

也尝试了这条线的变化,但我无法计算出除以 0 错误

awk -F, 'FNR==NR{a[$1,$2]; next ;b[$1,$2,$3]; next} $1,$2 in a {if ((Q=(b[$3]/$3) > 15) || (Q=($3/b[$3])) > 15 ){print Q,$0}}' file1 file2 
awk: cmd. line:1: (FILENAME=file2 FNR=1) fatal: division by zero attempted

【问题讨论】:

  • the difference between the 2 columns is > 15% 15% 什么?
  • 彼此,较低的#除以较高的#。 124/474 = 26%
  • 谢谢,我认为我的数学错了,我认为这条线 abc,5,474,124,26%,- 应该是 abc,5,474,124,74%,- = 474-124 / 474 = 74%跨度>

标签: awk


【解决方案1】:

如果分母在基本情况下为零,则需要处理,因为在这种情况下找不到相对变化,因此需要报告绝对变化。

$ awk -F, -v OFS=, '{k=$1 FS $2}
            FNR==NR {a[k]=$3; next}
            k in a  {if(a[k]) q=$3/a[k]-1;
                     else if($3) zero=1
                     else q=0
                     plus=q>0.15
                     minus=q<-0.15
                     q=q<0?-q:q; 
                     if(zero) plus=minus=0
                     if(plus || minus || zero)
                       print k,a[k],$3,(zero?100:int(100*q))"%",(plus?"+":minus?"-":"*")
                     q=zero=0}' file1 file2

abc,5,474,124,73%,-
def,10,136,435,219%,+
def,12,183,155,15%,-
xyz,19,0,124,100%,*

您可以将其放入 diff.awk 文件并使用 awk -f diff.awk file1 file2 运行 文件内容应该是

BEGIN{FS=OFS=","}
{k=$1 FS $2}
 ...  the code in between
   q=zero=0}

请注意,正文没有单引号。您可以使用正确的 shebang 使其可执行,但我认为这会更简单。

【讨论】:

  • 我尝试运行,但出现了大约 6 个不同的语法错误。我认为这是我的问题的一半,我不太了解 awk 以找出语法错误
  • @chadb 上面的代码似乎运行得很好。我用 4 种不同的 awks 进行了测试。
  • 现已测试,它与您的输出不匹配,但我认为您的计算不正确或执行了您指定之外的其他操作。
  • 谢谢,我需要做一些特别的事情来把它全部放在一条线上吗?我会再试一次,我编辑了上面的预期输出,你说得对,我的数学已经关闭了。
  • 如果没有换行符,你需要在语句之间使用分号。为什么需要一根线?是比赛吗?这可以稍微简化一点,但由于复杂的逻辑,仍然不能自然地适应单线。
猜你喜欢
  • 2012-10-18
  • 2015-03-25
  • 2019-09-08
  • 2023-03-11
  • 2015-12-29
  • 2020-09-22
  • 1970-01-01
  • 2017-03-20
  • 2020-02-15
相关资源
最近更新 更多