根据某些条件保留文件的某些行

时间:2015-04-23 08:29:25

标签: bash while-loop grep line

我有一个这样的档案:

K1   bla   STARTED
K1   bla   FINISHED
K2   blu   FINISHED
K3   bli   STARTED
K3   bli   DIED_SKIPPED_PERMANENTLY
K4   blo   STARTED
K5   ble   STARTED
K5   ble   DIED_SKIPPED_PERMANENTLY
K6   blou  STARTED
K6   blou  STARTED

由此,我想获取一个文件,其中,当第1列中的每个名称都有FINISHEDDIED_SKIPPED_PERMANENTLY时,只有包含此信息的行存在而不存在其他行(带有开始或其他事情)。 此外,如果两条线相同(如K6中的那条),我只想打印一条。

以我的例子为例,输出为:

K1   bla   FINISHED
K2   blu   FINISHED
K3   bli   DIED_SKIPPED_PERMANENTLY
K4   blo   STARTED
K5   ble   DIED_SKIPPED_PERMANENTLY
K6   blou  STARTED

我不能只通过

删除
grep -v STARTED 

因为对于某些名称,例如我的例子中的K4,只有这一行存在,我想知道它开始(或不是)所以我需要保留该信息。

我有一个文件,其中包含我从第1列获得的所有名称:

awk '{print $1}' file | sort | uniq > names    # 7,752 lines

我在考虑这种循环:

对于文件中出现的每个名称"名称",请执行:

如果其中一行$ line包含FINISHEDDIED_SKIPPED_PERMANENTLY,则只在我的输出中打印该行,而不打印其他行。 否则,请保留包含该名称的所有行。 但是删除相同的行。

这是一个想法,但我不知道如何做到这一点。 如果有人可以提供帮助,我将不胜感激

3 个答案:

答案 0 :(得分:1)

我们可以使用STARTED按字典顺序大于FINISHEDDIED_SKIPPED_PERMANENTLY并使用

的事实
sort filename | awk '!seen[$1,$2]++'

由于STARTED在字典上最大,因此在STARTED完成后,FINISHEDDIED_SKIPPED_PERMANENTLY行后将始终显示sort行。 awk代码通过如此排序的行趟过,只打印那些之前没有看到字段1和2的组合的行。

答案 1 :(得分:0)

使用awk和数组

awk '!a[$1]||/DIED_SKIPPED_PERMANENTLY|FINISHED/{a[$1]=$0}END{for(i in a)print a[i]}' f

输出

K1   bla   FINISHED
K2   blu   FINISHED
K3   bli   DIED_SKIPPED_PERMANENTLY
K4   blo   STARTED
K5   ble   DIED_SKIPPED_PERMANENTLY
K6   blou  STARTED

请注意,这是为了获得您已发布的预期输出,但不适用于实际描述。

答案 2 :(得分:0)

awk '$3 ~ /FINISHED|DIED_SKIPPED_PERMANENTLY/ && !a[$0]++' input

这只是检查第3列是否匹配FINISHED或DIED_SKIPPED_PERMANENTLY并将整行存储在数组a中,仅在第一次看到时才打印它。请注意,这将打印包含' FOO_FINISHED"第三栏,但这不应成为问题。但是,根据提供的示例输出,我认为您实际上在寻找:

awk '$1!=p && NR>1{print l}; {p=$1;l=$0}END{ if($1!=p)print l}' input
当列1中的键连续出现时,

打印第1列中出现给定字段的最后一行。