【问题标题】:AWK filter first and last row of given variable, discard the middle rowsAWK过滤给定变量的第一行和最后一行,丢弃中间行
【发布时间】:2019-04-22 10:39:38
【问题描述】:

我正在尝试通过使用 AWK 在制表符分隔的 txt 文件中选择给定变量的第一行和最后一行来过滤文件。

制表符分隔的文件如下所示:

1 apple  30
2 apple  35
3 apple  36
4 apple  20
5 pear   10
6 pear   30
7 pear   45
8 orange 16 

END 

我正在尝试使用 awk 进行处理,只打印 $2 中每个变量的第一行和最后一行(本例中的水果列)

我实际拥有的文件长度约为 35000 行,并且在我想用作过滤器的列中有 3000 个唯一变量(因此在上面的示例 col2 中)

我在想的方法是创建一个唯一 col2 值的数组(苹果、梨、橙),然后使用这个数组从较大的文件中提取第一个和最后一个值......但是一些关于命名的建议需要为每个索引变量选择第一行和最后一行将不胜感激。 :)

上面给出的输入文件,预期的输出是

1 apple  30
4 apple  20
5 pear   10
7 pear   45
8 orange 16

输出也需要包含只有一个条目的那些(在本例中为橙色)

【问题讨论】:

  • 文件是否在 column2 上排序?
  • 嗨,是的,文件在第 2 列排序。

标签: unix awk filtering


【解决方案1】:

一种方式:

awk '$2!=prev{if (pline){print pline;}print;}{prev=$2;pline=$0;}END{print pline;}' file | uniq

每次遇到新的第二列行时打印。在打印新的第 2 列行时,如果上一行不为空,则也打印该行。 uniq 是删除打印的重复行,以防其间存在单个记录。

【讨论】:

    【解决方案2】:

    即使相同的数据同时显示为给定键值的第一行和最后一行,或者数据包含空白行或0 行(假设您希望像其他行一样处理这些行,很容易如果没有跳过):

    $ cat tst.awk
    $2 != prev2 {
        if ( NR > 1 ) {
            print rec
        }
        beg = rec = $0
        prev2 = $2
        next
    }
    { rec = beg ORS $0 }
    END { print rec }
    
    $ awk -f tst.awk file
    1 apple  30
    4 apple  20
    5 pear   10
    7 pear   45
    8 orange 16
    

    【讨论】:

      【解决方案3】:

      在 gnu awk 上试过,不需要外部程序

      awk '{if($0~/^[a-z0-9]/) a[NR]=$0} END{f=1;asort(a); for(;i++<NR;){split(a[i],b);if(b[2]==$2||f){$1=b[1];$2=b[2];$3=b[3];if(f){f=0;print}} else if(b[2]){print;print b[1],($2=b[2]),b[3]}} }' d
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-11-04
        • 1970-01-01
        • 2015-06-24
        • 2020-06-20
        • 1970-01-01
        • 1970-01-01
        • 2021-11-27
        相关资源
        最近更新 更多