Unix awk命令返回所有匹配的行

时间:2017-09-21 06:17:47

标签: shell unix awk

我有一个类似下面的文件 -

A
B
C
D
E

-----

A
B
C
D
C

---

X
Y
A
B
XEC

---

当每个块的第五行是/包含E时,我希望返回前4行。我写了下面的命令,但它是错误的

awk '{a[NR]=$0} $0~s {f=NR} END {print a[f-4]; print a[f-6]; print a[f-8];}' s="E" file.txt

但它只返回最后一场比赛。我希望返回所有匹配的行。

对于上述条目,输出需要

A
B
C
D
---

X
Y
A
B

还有其他方法可以达到这个目的吗?

3 个答案:

答案 0 :(得分:3)

使用gawk:仅在gnu-awk

中支持多字符RS
awk -v RS='\n\n[-]+\n\n*' -v FS="\n" '$5 ~ /E/{printf "%s\n%s\n%s\n%s\n---\n",$1,$2,$3,$4}' inputfile
A
B
C
D
---
X
Y
A
B
---

答案 1 :(得分:3)

不确定你想要什么,你真的需要---然后换行符号???

使用tacawk,您可以尝试以下

  • 在一些正则表达式后打印N条记录:

    awk -v n=4 'c&&c--;/regexp/{c=n}' <input_file>

  • 在某些正则表达式之前打印N条记录:

    tac <input_file> | awk -v n=4 'c&&c--;/regexp/{c=n}' | tac

     ^                       ^              ^              ^
     |                       |              |              |
    reverse file  no of lines to print  when regexp found  again reverse  
    

<强>输入

$ cat infile
A
B
C
D
E

-----

A
B
C
D
C

---

X
Y
A
B
XEC

---

n=4

$ tac infile | awk -v n=4 'c&&c--;/E/{c=n}' | tac
A
B
C
D
X
Y
A
B

n=2

$ tac infile | awk -v n=2 'c&&c--;/E/{c=n}' | tac
C
D
A
B

答案 2 :(得分:0)

另一个awk(只有一个awk):

awk '
/^-/ && !prev{
  print;
  count=val="";
  prev=$0;
  next
}
/^-/ && prev{
  count=val="";
  prev=$0;
  next
}
/^ /{
  count=val="";
  next
}
NF && (\
  ++count==5 && $0~/E/){
     print val RS $0;
     val=count=""
}
{
  val=val?val ORS $0:$0;
}
'   Input_file

输出如下。

A
B
C
D
E
-----
X
Y
A
B
XEC

awk的说明:

awk '
/^-/ && !prev{           ##Checking conditions here if any line starts with -(dash) and variable named prev is NULL.
  print;                 ##printing the current line.
  count=val="";          ##Making variables count and val to NULL now.
  prev=$0;               ##Assigning the current line value to variable prev now.
  next                   ##Using next will skip all further statements.
}
/^-/ && prev{            ##Checking conditions if a line starts from -(dash) and variable prev value is NOT NULL.
  count=val="";          ##Making values of variables named count and val to NULL.
  prev=$0;               ##Assigning variable prev to current line.
  next                   ##Using next will skip all further statements.
}
/^ /{                    ##Checking condition here if a line starts with space.
  count=val="";          ##Making variables named count and val to NULL.
  next                   ##Using next will skip all further statements.
}
NF && (\
  ++count==5 && $0~/E/){ ##Checking conditions if a line has value of NF(means not a blank line) and variable count(whose value is pre-increasing to 1 each time cursor comes here) is equal to 5 and current line has capital E in it then do following.
     print val RS $0;    ##printing variable named val and RS(record separator) with current line.
     val=count=""        ##Nullifying the variables named val and count here.
}
{
  val=val?val ORS $0:$0; ##Creating a variable named val and its value is concatenating to itself.
}
' Input_file             ##Mentioning the Input_file name here.