Awk 查找跨不同线条的图案
我有这样一个文件(test.txt): 我想搜索“abc\nghi”和“def”所附的78。目前,我知道我可以通过以下方式做到这一点:Awk 查找跨不同线条的图案,awk,sed,grep,Awk,Sed,Grep,我有这样一个文件(test.txt): 我想搜索“abc\nghi”和“def”所附的78。目前,我知道我可以通过以下方式做到这一点: cat test.txt | awk '/abc/,/def/' | awk '/ghi/,'/def/' 有更好的方法吗?一种方法是使用标志 $ awk '/ghi/ && p~/abc/{f=1} f; /def/{f=0} {p=$0}' test.txt ghi 78 def {p=$0}这将保存输入行以备将来使用 /ghi/&p~
cat test.txt | awk '/abc/,/def/' | awk '/ghi/,'/def/'
有更好的方法吗?一种方法是使用标志
$ awk '/ghi/ && p~/abc/{f=1} f; /def/{f=0} {p=$0}' test.txt
ghi
78
def
这将保存输入行以备将来使用{p=$0}
如果当前行包含/ghi/&p~/abc/{f=1}
且前一行包含ghi
abc
f只要设置了标志,代码>打印输入记录
如果行包含/def/{f=0}
def
如果你只想要这两个边界之间的线
$ awk '/ghi/ && p~/abc/{f=1; next} /def/{f=0} f; {p=$0}' ip.txt
78
$ awk '/12/ && p~/abc/{f=1; next} /def/{f=0} f; {p=$0}' ip.txt
34
另请参见awk解决方案:
awk '/ghi/ && r=="abc"{ f=1; n=NR+1 }f && NR==n{ v=$0 }v && NR==n+1{ print v }{ r=$0 }' file
输出:
78
奖金GNU awk方法:
awk -v RS= 'match($0,/\nabc\nghi\n(.+)\ndef/,a){ print a[1] }' file
这并不是很干净,但您可以将记录分隔符重新定义为正则表达式,即
abc\nghi\n | \ndef
。但是,这会创建多个记录,您需要跟踪哪些记录在正确的记录之间。使用awk,您可以使用RT
检查找到了哪些RS
awk 'BEGIN{RS="abc\nghi\n|\ndef"}
(RT~/abc/){s=1}
(s==1)&&(RT~/def/){print $0}
{s=0}' file
这是:
- 将
设置为RS
或abc\nghi\n
\ndef
- 检查是否找到记录,如果
包含RT
您找到了第一条记录abc
- 如果发现第一个
包含RT
,则打印def
grep
备选方案
$ grep -Pazo '(?s)(?<=abc\nghi)(.*)(?=def)' file
$grep-Pazo'(?s)(?你可以用sed来做这件事。它并不理想,因为它实际上不理解记录,但它可能适合你
sed -Ene 'H;${x;s/.*\nabc\nghi\n([0-9]+)\ndef\n.*/\1/;p;}' input.txt
基本情况如下:
H
-将当前行附加到sed的“保留空间”
${
-指定一系列命令的开始,这些命令将在文件结束时运行
x
-将保留空间与模式空间交换,以便将来的替换将使用H
s/../../
-分析模式空间(现在是多行),捕获问题中指定的数据,用括号内的表达式替换整个模式空间
p
-打印结果
这里的一个重要因素是正则表达式是ERE,因此-E
选项很重要。如果您的sed版本使用其他选项来启用对ERE的支持,请改用该选项
另一个需要考虑的问题是,上面的正则表达式采用Unix样式的行尾。如果您试图处理在DOS或Windows上生成的文本文件,正则表达式可能需要稍微不同。虽然您只想搜索78,但最终的输出应该是什么?嗯……很好……我认为OP尝试的命令给出了预期的输出ut..但可能只需要两行之间的行,因此我编辑了我的回答downvote,没有任何评论,对于可能的答案改进没有太多意义/意义。因此,这种downvote是无意义的,仅适用于grep。在BSD中,-P
选项不起作用(包括macOS),不过,pcregrep
通常作为附加包提供。
sed -Ene 'H;${x;s/.*\nabc\nghi\n([0-9]+)\ndef\n.*/\1/;p;}' input.txt