{awk} 如何读取一行并将 $ 与其 next/previous 行进行比较?
{awk} How to read a line and compare a $ with its next/previous line?
下面的命令用于读取包含 7682 行的输入文件:
我使用 --field-separator 然后将一些字段转换成我需要的,grep 去掉了我不需要的前两行。
awk --field-separator=";" '(<15) {print int(a=((-1)/480)+1) " " (-((int(a)-1)*480)) " " (20*log()/log(10))}' 218_DW.txt | grep -v "0 480 -inf"
我使用 ($1<15) 所以我只打印 14 行,更适合测试。我得到的输出正是我想要的,但是,我还需要做更多的事情:
1 1 48.2872
1 2 48.3021
1 3 48.1691
1 4 48.1502
1 5 48.1564
1 6 48.1237
1 7 48.1048
1 8 48.015
1 9 48.0646
1 10 47.9472
1 11 47.8469
1 12 47.8212
1 13 47.8616
1 14 47.8047
从上面看,$1 将从 1-16 递增,$2 从 1-480 递增,它始终是连续的,
所以当它到达 16 480 47.8616 时,它从 2 1 47.8616 重新开始,直到最后一行是 16 480 10.2156
所以我得到 16*480=7680 行
我想做的很简单,但是,我不明白:)
我想将当前行与下一行进行比较。但不是所有字段,只有$3,它是一个以dB为单位的值,当$2增加时减少。
例如:
The current line is 1 1 48.2872=a
Next line is 1 2 48.3021=b
如果 [ (a - b) > 6 ] 则打印 $1 $2 $3
当然 (a - b) 必须是绝对值,始终 > 0。
野兽将能够将当前行(仅 $3)与下一行和上一行($3)进行比较。
像这样:
1 3 48.1691=a
1 4 48.1502=b
1 5 48.1564=c
如果 [ ABS(b - a) > 6 ] 或如果 [ ABS(b - c) > 6 ] 那么打印 $1 $2 $3
当然,第一行只能与下一行进行比较,最后一行只能与上一行进行比较。可能吗?
试试这个:
#!/usr/bin/awk -f
function abs(x) {
if (x >= 0)
return x;
else
return -1 * x;
}
function compare(a,b) {
return abs(a - b) > 6;
}
function update() {
before_value = current_value;
current_line = [=10=];
current_value = ;
}
BEGIN {
line_n = 1;
}
#Edit: added to skip blank lines and differently formatted lines in
# general. You could add some error message and/or exit function
# here to detect badly formatted data.
NF != 3 {
next;
}
line_n == 1 {
update();
line_n += 1;
next;
}
line_n == 2 {
if (compare(current_value, ))
print current_line;
update();
line_n += 1;
next;
}
{
if (compare(current_value, before_value) && compare(current_value, ))
print current_line;
update();
}
END {
if (compare(current_value, before_value)) {
print current_line;
}
}
有趣的是,我从一个旧项目中得到了这段代码,我必须做基本上相同的事情。为您稍微调整一下。我认为它解决了您的问题(至少我是这样理解的)。如果没有,它应该会为您指明正确的方向。
运行 awk 脚本的说明:
假设您保存的代码名为 "awkscript",数据文件名为 "datafile",并且它们都在当前文件夹中,您应该首先将脚本标记为可执行文件 chmod +x awkscript
然后执行它,将数据文件作为参数传递给 ./awkscript datafile
或将其用作管道序列的一部分,如 cat datafile | ./awkscript
.
将当前行与上一行进行比较是微不足道的,所以我认为您遇到的问题是您不知道如何将当前行与下一行进行比较。只需保留前 2 行而不是 1 行,并始终在实际读取为 $0 的行之前的行上操作,即本例中存储在数组 p1
中的行(p2
是它之前的行[=13=]
是它后面的一行):
function abs(val) { return (val > 0 ? val : -val) }
NR==2 {
if ( abs(p1[3] - ) > 6 ) {
print p1[1], p1[2], p1[3]
}
}
NR>2 {
if ( ( abs(p1[3] - p2[3]) > 6 ) || ( abs(p1[3] - ) > 6 ) ) {
print p1[1], p1[2], p1[3]
}
}
{ prev2=prev1; prev1=[=10=]; split(prev2,p2); split(prev1,p1) }
END {
if ( ( abs(p1[3] - p2[3]) > 6 ) ) {
print p1[1], p1[2], p1[3]
}
}
下面的命令用于读取包含 7682 行的输入文件: 我使用 --field-separator 然后将一些字段转换成我需要的,grep 去掉了我不需要的前两行。
awk --field-separator=";" '(<15) {print int(a=((-1)/480)+1) " " (-((int(a)-1)*480)) " " (20*log()/log(10))}' 218_DW.txt | grep -v "0 480 -inf"
我使用 ($1<15) 所以我只打印 14 行,更适合测试。我得到的输出正是我想要的,但是,我还需要做更多的事情:
1 1 48.2872
1 2 48.3021
1 3 48.1691
1 4 48.1502
1 5 48.1564
1 6 48.1237
1 7 48.1048
1 8 48.015
1 9 48.0646
1 10 47.9472
1 11 47.8469
1 12 47.8212
1 13 47.8616
1 14 47.8047
从上面看,$1 将从 1-16 递增,$2 从 1-480 递增,它始终是连续的, 所以当它到达 16 480 47.8616 时,它从 2 1 47.8616 重新开始,直到最后一行是 16 480 10.2156
所以我得到 16*480=7680 行
我想做的很简单,但是,我不明白:)
我想将当前行与下一行进行比较。但不是所有字段,只有$3,它是一个以dB为单位的值,当$2增加时减少。
例如:
The current line is 1 1 48.2872=a
Next line is 1 2 48.3021=b
如果 [ (a - b) > 6 ] 则打印 $1 $2 $3
当然 (a - b) 必须是绝对值,始终 > 0。
野兽将能够将当前行(仅 $3)与下一行和上一行($3)进行比较。 像这样:
1 3 48.1691=a
1 4 48.1502=b
1 5 48.1564=c
如果 [ ABS(b - a) > 6 ] 或如果 [ ABS(b - c) > 6 ] 那么打印 $1 $2 $3
当然,第一行只能与下一行进行比较,最后一行只能与上一行进行比较。可能吗?
试试这个:
#!/usr/bin/awk -f
function abs(x) {
if (x >= 0)
return x;
else
return -1 * x;
}
function compare(a,b) {
return abs(a - b) > 6;
}
function update() {
before_value = current_value;
current_line = [=10=];
current_value = ;
}
BEGIN {
line_n = 1;
}
#Edit: added to skip blank lines and differently formatted lines in
# general. You could add some error message and/or exit function
# here to detect badly formatted data.
NF != 3 {
next;
}
line_n == 1 {
update();
line_n += 1;
next;
}
line_n == 2 {
if (compare(current_value, ))
print current_line;
update();
line_n += 1;
next;
}
{
if (compare(current_value, before_value) && compare(current_value, ))
print current_line;
update();
}
END {
if (compare(current_value, before_value)) {
print current_line;
}
}
有趣的是,我从一个旧项目中得到了这段代码,我必须做基本上相同的事情。为您稍微调整一下。我认为它解决了您的问题(至少我是这样理解的)。如果没有,它应该会为您指明正确的方向。
运行 awk 脚本的说明:
假设您保存的代码名为 "awkscript",数据文件名为 "datafile",并且它们都在当前文件夹中,您应该首先将脚本标记为可执行文件 chmod +x awkscript
然后执行它,将数据文件作为参数传递给 ./awkscript datafile
或将其用作管道序列的一部分,如 cat datafile | ./awkscript
.
将当前行与上一行进行比较是微不足道的,所以我认为您遇到的问题是您不知道如何将当前行与下一行进行比较。只需保留前 2 行而不是 1 行,并始终在实际读取为 $0 的行之前的行上操作,即本例中存储在数组 p1
中的行(p2
是它之前的行[=13=]
是它后面的一行):
function abs(val) { return (val > 0 ? val : -val) }
NR==2 {
if ( abs(p1[3] - ) > 6 ) {
print p1[1], p1[2], p1[3]
}
}
NR>2 {
if ( ( abs(p1[3] - p2[3]) > 6 ) || ( abs(p1[3] - ) > 6 ) ) {
print p1[1], p1[2], p1[3]
}
}
{ prev2=prev1; prev1=[=10=]; split(prev2,p2); split(prev1,p1) }
END {
if ( ( abs(p1[3] - p2[3]) > 6 ) ) {
print p1[1], p1[2], p1[3]
}
}