{awk}如何读取一行并将$与下一行/上一行进行比较?

时间:2015-02-08 04:00:05

标签: bash awk

以下命令用于读取包含7682行的输入文件: 我使用--field-separator然后将一些字段转换成我需要的字段,并且grep摆脱了我不需要的第一行。

awk --field-separator=";" '($1<15) {print int(a=(($1-1)/480)+1) " " ($1-((int(a)-1)*480)) " " (20*log($6)/log(10))}' 218_DW.txt | grep -v "0 480 -inf"

我使用($ 1&lt; 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)必须是绝对值,总是&gt; 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

但当然第一行只能与下一行进行比较,最后一行只能与前一行进行比较。有可能吗?

2 个答案:

答案 0 :(得分:2)

试试这个:

#!/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 = $0;
        current_value = $3;
}

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, $3))
                print current_line;
        update();
        line_n += 1;
        next;
}

{
        if (compare(current_value, before_value) && compare(current_value, $3))
                print current_line;
        update();
}

END {
        if (compare(current_value, before_value)) {
                print current_line;
        }
}

有趣的是,我有一个旧项目的代码,我必须做的基本相同的事情。适应它有点适合你。我认为它解决了你的问题(至少我是如何理解的)。如果它没有,它应该指向正确的方向。

运行awk脚本的说明:

假设您使用名称&#34; awkscript&#34;保存了代码,数据文件名为&#34; datafile&#34;并且它们都在当前文件夹中,您应该首先使用chmod +x awkscript将脚本标记为可执行文件,然后执行它将数据文件作为参数传递给./awkscript datafile,或者将其用作一系列管道的一部分,如在cat datafile | ./awkscript

答案 1 :(得分:2)

将当前行与前一行进行比较是微不足道的,所以我认为您遇到的问题是您无法弄清楚如何将当前行与下一行进行比较。只保留2个前一行而不是1,并且总是在实际读取为$ 0的行之前操作,即在此示例中存储在数组p1中的行(p2是在它之前的行和$0之后的行):

function abs(val) { return (val > 0 ? val : -val) }
NR==2 {
    if ( abs(p1[3] - $3) > 6 ) {
        print p1[1], p1[2], p1[3]
    }
}
NR>2 {
    if ( ( abs(p1[3] - p2[3]) > 6 ) || ( abs(p1[3] - $3) > 6 ) ) {
        print p1[1], p1[2], p1[3]
    }
}
{ prev2=prev1; prev1=$0; split(prev2,p2); split(prev1,p1) }
END {
    if ( ( abs(p1[3] - p2[3]) > 6 ) ) {
        print p1[1], p1[2], p1[3]
    }
}