如何从图案中打印第n行?

时间:2013-09-25 10:40:50

标签: linux bash sed awk grep

我正在尝试制作一个脚本,以简短格式汇总包含以下日志的文件。

日志片段:

$ cat input.txt
ffffff     1301 2012-08-29T03:13:33 clr         crit
Some serious problem
cccc                            dddddd        eeeeee
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Some serious problem in system.

ffffff     1302 2012-08-29T03:13:33 set         min
Some serious problem
cccc                            dddddd        eeeeee
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Some minor problem in system. 

期望的输出:

2012-08-29T03:13:33 clr crit Some serious problem in system.
2012-08-29T03:13:33 set min Some minor problem in system. 

我在approch下面尝试过:

$ cat input.txt | grep -iE "set|upd|clr" | awk '{print $3,$4,$5}' >file1
12-08-29T03:13:33  clr crit
12-08-29T03:13:33  set min

下面的命令从模式“T”给出第5行,但问题在于所需的文本行,在某些情况下,它在第5行,在某些情况下,它在第4行。

$ awk '/T/ { show[NR+4]++  } show[NR]' input.txt >file2

$ paste file1 file2 

查询:

在某些情况下,它位于第5行,在某些情况下,它位于第4行。我怎样才能确保找到确切的文字。如果可能,请告诉我。

3 个答案:

答案 0 :(得分:2)

解决此问题的正确方法是将awks Record Separator设置为空字符串,以便awk知道您的输入记录由空行分隔:

$ awk -v RS= -F'\n' '{split($1,a,/ +/); print a[3],a[4],a[5],$NF}' file
2012-08-29T03:13:33 clr crit Some serious problem in system.
2012-08-29T03:13:33 set min Some minor problem in system.

这种方式如果/当你想要在未来打印记录的其他部分或打印记录数量的计数或仅打印基于某些关键字段或其他任何内容的唯一记录时,这是非常微不足道的,因为awk知道关于和是根据记录进行操作。

答案 1 :(得分:1)

看起来您的固定记录大小为7行,因此您可以使用awk执行以下操作:

$ awk 'NR%7==1{printf "%s %s %s ",$3,$4,$5}NR%7==6' file
2012-08-29T03:13:33 clr crit Some serious problem in system.
2012-08-29T03:13:33 set min Some minor problem in system.

这使用模数运算符在记录的第一行打印第三,第四和第五个字段,并打印整个第六行。

答案 2 :(得分:1)

这个awk单行应该更强大:

awk '$3 ~ /[0-9]+-[0-9]+-/{printf "%s%s%s%s%s", $3, OFS, $4, OFS, $5; 
     for(i=0; i<5; i++) getline; print OFS $0}' input.txt

2012-08-29T03:13:33 clr crit Some serious problem in system.
2012-08-29T03:13:33 set min Some minor problem in system.

UPDATE ::没有getline的解决方案:

awk '$3 ~ /[0-9]+-[0-9]+-/{s=NR; printf "%s%s%s%s%s", $3, OFS, $4, OFS, $5}
     NR==s+5{print OFS $0}' input.txt