在同一列中打印比上面和下面 3 个步骤的值至少大 2 倍的值

在同一列中打印比上面和下面 3 个步骤的值至少大 2 倍的值

我有一个清单

2
2
2
3
2
2
2
4
2
2
2

我想在同一列中打印比上面和下面 3 个步骤的值至少大 2 倍的值。

输出应该是

4

怎么做?我也问过类似的问题这里,只是为了更好地说明我写在这里,谢谢。

20171006 更新:抱歉过度简化了我的实际输入文件,它实际上是一个表而不是一个列表,我需要在多个列(第 2、3、4 列等)中选择并打印第 1 列。我如何合并该列这样的脚本中的信息?

A 2 2 2
B 2 2 2
C 2 2 2
D 3 3 3
E 2 2 2
F 2 2 2
G 2 2 2
H 4 4 4
I 2 2 2 
J 2 2 2 
K 2 2 2 

并得到

H

答案1

你可以在awk.您需要保存前 6 行,以便将倒数第 3 行与倒数第 6 行以及当前行进行比较。为此,常见的技巧是使用环形缓冲区,它是一个由要保留的行数索引的NR%6数组6

awk '
  NR > 6 {
    x = saved[NR%6]; y = saved[(NR - 3) % 6]; z = $0
    if (y >= 2*x && y >= 2*z) print y
  }
  {saved[NR % 6] = $0}'  < file

对于您的编辑:保存要比较的键和值:

awk -v key=1 -v value=2 '
  NR > 6 {
    x = saved_value[NR%6]; y = saved_value[(NR - 3) % 6]; z = $value
    if (y >= 2*x && y >= 2*z) print saved_key[(NR - 3) % 6]
  }
  {saved_key[NR % 6] = $key; saved_value[NR % 6] = $value}'  < file

其中key是要打印的列的索引以及value包含要比较的值的列。

或者根据您想要的基于第 2、3、4 列(如平均值)的任何指标:

awk '
  {metric = ($2 + $3 + $4) / 3}
  NR > 6 {
    x = saved_metric[NR%6]; y = saved_metric[(NR - 3) % 6]; z = $metric
    if (y >= 2*x && y >= 2*z) print saved_key[(NR - 3) % 6]
  }
  {saved_key[NR % 6] = $key; saved_metric[NR % 6] = $metric}'  < file

答案2

不读取内存中的整个文件:

paste <(tail -n+4 file.txt | head -n-3) <(head -n-6 file.txt) <(tail -n+7 file.txt) |
    awk '$1 >= 2*$2 && $1 >= 2*$3 {print $1}'

<(...)这需要一个可以处理构造(fi AT&Tkshbash)的 shellzshhead支持负偏移量的实现。

解释:上面的命令paste将当前值、上面 3 步的值和下面 3 步的值放在同一行;该awk命令检查 2 倍大的条件。

答案3

awk解决方案:

awk 'function mean(sum){ 
          m=sum/3; return (int(m) == m)? m: int(m)+1 
     }
     { a[NR]=$0 }
     END{ 
         for(i=4;i<=NR-3;i++) 
             if (a[i]>=mean(a[i-3]+a[i-2]+a[i-1])*2 &&
                a[i]>=mean(a[i+3]+a[i+2]+a[i+1])*2) 
             print a[i] 
     }' file

  • a[NR]=$0- 将所有值收集到a以记录号索引的数组中NR

输出:

4

答案4

因此,您必须保留 3 + 1 + 3 输入行的滑动窗口才能做到这一点。

awk -vn=3 -va=2 'BEGIN { N=2*n+1 } { t=(NR-n)%N; m=NR%N; b=(NR+n)%N; w[b]=$0 } NR >= N && w[m] >= a*w[t] && w[m] >= a*w[b] { print w[m] }' file

n这将打印满足条件的所有值,还有一个额外的好处,您可以通过调整命令行上的变量(change)轻松修改距离,并通过更改(change )-vn=3重量来轻松修改距离。a-va=2

该代码将最后 N 个值存储在循环缓冲区中,其中 N 为 2*n + 1 w。如果中间值w[m]大于a缓冲区中第一个值w[t]t对于“顶部”)的倍,并且a比缓冲区中最后一个值w[b]b对于“底部”)大的倍,则将其打印。


剧本awk揭晓:

BEGIN   { N = 2*n + 1 }

        {
            t = (NR - n)%N
            m = NR%N
            b = (NR + n)%N
            w[b] = $0
        }

NR >= N && w[m] >= a*w[t] && w[m] >= a*w[b] { print w[m] }

相关内容