awk - 只打印重复的第一行和它下面的行

时间:2013-05-14 15:10:54

标签: database linux command-line awk matching

我有一个需要一些操作的大型数据库文件。基本上我需要避免重复的字段一由'|'分隔为:

-- TITLE1 | TITLE2   |T3   |TITLE4|TITLE5 
----------|----------|-----|------|---------------
--
DATA1   | SAME     |     |      |  blah blah
ELIGIBLE  | x1 
DATA1   | SAME     |     | blah |  blah
ELIGIBLE  | x2 
DATA1   | SAME     |     | blah |  blah blah
ELIGIBLE  | x2 
DATA2   | SAME     |     |      |  blah blah
ELIGIBLE  | y1 
DATA2   | SAME     |     | blah |  blah
ELIGIBLE  | y2
DATA2   | SAME     |     | blah |  blah blah blah blah
ELIGIBLE  | y2
DATA3   | SAME     |     |      |  blah blah
ELIGIBLE  | z1
DATA3   | SAME     |     | blah |  blah
ELIGIBLE  | z2
DATA3   | SAME     |     | blah |  blah blah blah blah
ELIGIBLE  | z2

我正在使用的代码是

BEGIN{ FS = "|" }
{
count[$1]++;
if (count[$1] == 1)
first [$1] = $0;
if (count[$1] > 1)
print first[$1]
NR==1;
}

但它给了我输出:

-- TITLE1 | TITLE2   |T3   |TITLE4|TITLE5 
----------|----------|-----|------|---------------
--
DATA1   | SAME     |     |      |  blah blah
ELIGIBLE  | x1 
DATA2   | SAME     |     |      |  blah blah
DATA3   | SAME     |     |      |  blah blah

我更喜欢这样的输出:

-- TITLE1 | TITLE2   |T3   |TITLE4|TITLE5 
----------|----------|-----|------|---------------
--
DATA1   | SAME     |     |      |  blah blah
ELIGIBLE  | x1 
DATA2   | SAME     |     |      |  blah blah
ELIGIBLE  | y1 
DATA3   | SAME     |     |      |  blah blah
ELIGIBLE  | z1 

我并不关心标题栏,但是需要它来显示所概述的数据。很抱歉业余的解释,但任何解决方案的帮助将不胜感激。当谈到linux命令行脚本时,我是一个新手,所以如果任何人也可以解释为什么我的答案是错误的,我将不胜感激。我不仅限于awk,可以使用任何命令解决方案。我只是想用awk尝试解决方案。

2 个答案:

答案 0 :(得分:0)

你可以试试这个:

awk -F\| '(printed!=0 && /ELIGIBLE/) {print; printed=0;} (!seen[$1] && $1 !~ /ELIGIBLE/) { print; printed = 1; seen[$1] = 1;  }' 

虽然几乎肯定有更好的方法。

ETA:在网络上有一个很好的Awk教程here和其他一些教程,还有一些好书。但基本上,awk程序是一系列模式和代码块,可以在与该模式匹配的每条记录(默认行)上运行。

awk '/foo/          { do this for lines that contain "foo" anywhere }
     ($1 == "bar")  { do this for lines whose first field is exactly "bar' }
     ($NF ~ /baz/)  { do this for lines whose last field contains "baz" }
     (NF == 1)      { do this for lines with exactly one field }
     (NR == 10)     { do this only on the 10th line }'

如果没有模式,则该块在每一行上运行。

awk '{print $NF}'   # print the last field of every line

如果没有块而只是一个模式,那么匹配的行将保持不变:

awk '/foo/'      # same as grep foo

在处理任何输入之前运行标记为BEGIN的块;在处理完所有输入后运行标记为END的块。

awk 'BEGIN { t = 0 } {t += $NF} END { print t }'   # print total of last column 

但实际上未初始化的变量在算术中被视为0,因此您可以跳过初始化:

awk '{t += $NF} END {print t}'

某些版本的awk需要分号;或模式/块对之间的换行符

答案 1 :(得分:0)

此行适用于您的示例。 (数据分类,在线数据,在线符合条件......)如果格式发生变化,则无法保证为您的实际数据工作。你必须自己测试一下。

标题/标题被跳过。

awk -F'|' '!(NR%2){next}$1 in a{next}{print;a[$1];getline;print}' file

试一试:

kent$  awk -F'|' '!(NR%2){next}$1 in a{next}{print;a[$1];getline;print}' file
DATA1   | SAME     |     |      |  blah blah
ELIGIBLE  | x1 
DATA2   | SAME     |     |      |  blah blah
ELIGIBLE  | y1 
DATA3   | SAME     |     |      |  blah blah
ELIGIBLE  | z1