我有一个清单
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&Tksh
或bash
)的 shellzsh
和head
支持负偏移量的实现。
解释:上面的命令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] }