Unix - 返回类似值的第一行和最后一行

时间:2016-12-02 02:23:28

标签: unix awk sed grep

我有一张这样的表:

1000    2000    Ally  
1001    2001    Ally  
1002    2002    Ally  
1003    2003    Ally  
2000    4000    Kate  
2010    4010    Kate  
2020    4020    Kate  
3000    9000    Lisa

我希望它在第3列具有相同值时返回第一行和最后一行。在这种情况下,它将返回:

1000    2000    Ally  
1003    2003    Ally  
2000 4000 Kate  
2020 4020 Kate  
3000    9000    Lisa

无论如何使用awk / sed / grep来执行此操作?感谢。

3 个答案:

答案 0 :(得分:2)

使用awk

NR == 1   {first=last=$0; key=$3 }
$3 == key {last=$0}
$3 != key {print first; if(first != last) print last; 
           first=last=$0; key=$3}
END       {print first; if(first != last) print last}

适用于您的数据集

未在其他任何方面进行测试

Per @ James-Brown在评论中的要求 打印重复的版本

NR ==1    {print; key=$3 }
$3 == key {last=$0}
$3 != key {print last "\n" $0; key=$3}
END       {print last}

(可能对其他数据做了其他错误)

答案 1 :(得分:1)

您可以使用这个简单的awk 1-liner打印第3列的每个不同值的第一个和最后一个记录:

awk '!arr[$3] {arr[$3]=$0; if(prevline) print prevline; print} {prevline=$0}' file

在这种情况下,关联数组是一个很大的帮助。

示例运行:

$ cat file 
1000    2000    Ally  
1001    2001    Ally  
1002    2002    Ally  
1003    2003    Ally  
2000    4000    Kate  
2010    4010    Kate  
2020    4020    Kate  
3000    9000    Lisa
$ awk '!arr[$3] {arr[$3]=$0; if(prevline) print prevline; print} {prevline=$0}' file
1000    2000    Ally  
1003    2003    Ally  
2000    4000    Kate  
2020    4020    Kate  
3000    9000    Lisa

答案 2 :(得分:0)

我无法想出任何聪明的东西,他们似乎都失败了。我责备TGIF,但让我们选择这个:

$ awk '{
           if($3 in first)
               last[$3]=$0; 
           else 
               first[$3]=$0
       } 
       END {
           for(i in first) 
               print first[i] ((i in last)?ORS last[i]:"")
       }' file # | sort -k3 -k1
2000    4000    Kate
2020    4020    Kate
3000    9000    Lisa
1000    2000    Ally
1003    2003    Ally

缺点是订单不会与原始文件中的订单相同,但可以使用sort保存。好处是匹配的记录不必在源文件中彼此相邻。