awk
这里是新手。
假设我有两列数据,并且我想计算增长率,由 delta(y)/delta(x) 给出。我将如何在awk
脚本中执行此操作?到目前为止我所学到的仅涉及逐行操作,并且我不确定如何处理多行。
注意:假设我有 N 个数据点,我将获得 N-1 个斜率/速率值。
例子:
输入
x y 2 4 3 5 4 7
输出
Slope - 1 2
这里是awk
最好的选择吗?或者其他工具更好吗?
答案1
使用变量来存储需要从一行到下一行记住的数据。
输出中的第 N+1 行是根据输入中的第 N 行和第 N+1 行计算得出的,因此您需要变量来存储前一行的内容。每行有两个字段,因此每个字段使用一个变量。
第 1 行和第 2 行得到特殊处理(标题行,数据不足)。您可以通过测试特殊变量来匹配特定的行号NR
。该指令next
导致当前行的其余处理被跳过。
由于这个处理相当简单,因此使用变量来表示上一行的内容就足够了。处理完当前行后,使用处理上一行时设置的变量,将当前行的内容存储到变量中。
NR == 1 { print "Slope"; next; }
NR == 2 { print "-"; }
NR >= 3 { print ($2 - y) / ($1 - x) }
NR >= 2 { x = $1; y = $2; }
回想一下,awk 依次运行每个输入行的代码,每个花括号组之前的表达式是运行该组的条件,因此这相当于以下伪代码:
for each line {
NR = current line number;
$1 = first field; $2 = second field;
if (NR == 1) { print "Slope"; next; }
…
}
或者,如果为前一行的数据和当前行的数据都指定名称,您可能会发现代码更具可读性。在当前行处理结束时,将数据从“当前”变量传输到“上一个”变量。
NR == 1 { print "Slope"; next; }
NR == 2 { print "-"; }
NR >= 2 { current_x = $1; current_y = $2; }
NR >= 3 { print (current_y - previous_y) / (current_x - previous_x) }
NR >= 2 { previous_x = current_x; previous_y = current_y; }
答案2
$ awk 'NR==1 { print; next; }; '\
' NR==2 { former_x=$1; former_y=$2; $3="-"; print; next; };'\
' { $3=($2-former_y)/($1-former_x); print; former_x=$1; former_y=$2; }' input
x y Slope
2 4 -
3 5 1
4 7 2
第一行只是按原样打印。
在以下所有行中,您必须存储列中的值x
,y
以便它们可用于以下行中的计算。第 2 行经过特殊处理,因为还没有什么可计算的。
在以下所有行中,计算比率,将其作为新字段添加到该行,打印该行,并存储该行的值。
答案3
假设你的输入是
x y
2 4
3 5
4 7
4 8
然后
awk 'NR==1{print $0" Slope"; getline}
{dx=($1-xold); dy=($2-yold);$3=(xold&&dx!=0)?dy/dx:"-"; xold=$1; yold=$2; print}' file
给你
x y Slope
2 4 -
3 5 1
4 7 2
4 8 -
解释-o
awk 'NR==1{print $0" Slope"; getline}
如果它是第一条记录/行NR==1
,则将其与附加标题一起打印并跳转到下一行getline
{dx=($1-xold); dy=($2-yold);
计算dx
并dy
$3=(xold&&dx!=0)?dy/dx:"-";
如果xold
已初始化(仅在该测试后发生在第 2 行,因此仅在第 2 行失败)并且dx!=0
(没有 div 0 错误)则$3=dy/dx
否则$3="-"
xold=$1; yold=$2;
然后更新xold
和yold
值到该记录/行上的当前 x 和 y
print}' file
然后打印整个记录/行(包括新的$3
)