我试图仅打印<N>
搜索模式之前的第 th 行。打印搜索模式之前的grep -B<N>
所有行。<N>
我看到了 awk 代码这里只能打印<N>
搜索模式后的第 3 行。
awk 'c&&!--c;/pattern/{c=N}' file
如何修改它以仅打印<N>
每行匹配之前的第 th 行pattern
?例如,这是我的输入文件
...
...
0.50007496 0.42473932 0.01527831
0.99997456 0.97033575 0.44364198
Direct configuration= 1
0.16929051 0.16544726 0.16608723
0.16984300 0.16855274 0.50171112
...
...
0.50089841 0.42608090 0.01499159
0.99982054 0.97154975 0.44403547
Direct configuration= 2
0.16931296 0.16553376 0.16600890
0.16999941 0.16847055 0.50170694
...
我需要一个可以返回2nd line
搜索字符串之前的命令Direct configuration
。我正在尝试运行这个SUSE Linux
答案1
需要使用行缓冲区。
尝试一下这个:
awk -v N=4 -v pattern="example.*pattern" '{i=(1+(i%N));if (buffer[i]&& $0 ~ pattern) print buffer[i]; buffer[i]=$0;}' file
将值设置N
为要打印的图案之前的第 N 行。
pattern
将值设置为要搜索的正则表达式。
buffer
是一个元素数组N
。它用于存储线路。每次找到该模式时,N
都会打印该模式之前的第 3 行。
答案2
该代码不适用于前面的行。要获取匹配模式之前的行,您需要以某种方式保存已处理的行。由于awk
只有关联数组,我想不出一种同样简单的方法来执行您想要的操作awk
,因此这是一个 perl 解决方案:
perl -ne 'push @lines,$_; print $lines[0] if /PAT/; shift(@lines) if $.>LIM;' file
更改PAT
为您想要匹配的模式和LIM
行数。例如,要在每次出现 之前打印第 5 行foo
,您可以运行:
perl -ne 'push @lines,$_; print $lines[0] if /foo/; shift(@lines) if $.>5;' file
解释
perl -ne
:逐行读取输入文件并将给定的脚本应用于-e
每一行。push @lines,$_
:将当前行($_
)添加到数组中@lines
。print $lines[0] if /PAT/
:如果当前行与所需模式匹配,则打印数组中的第一个元素@lines
( )。$lines[0]
shift(@lines) if $.>LIM;
:$.
是当前行号。如果大于限制,则从数组中删除第一个值@lines
。结果是@lines
总是有最后LIM
几行。
答案3
tac file | awk 'c&&!--c;/pattern/{c=N}' | tac
但是,当 N 行内有多个匹配项时,这与“转发”用例具有相同的遗漏。
当输入从正在运行的进程通过管道传输时,它不会很好地工作,但当输入文件完整且不增长时,这是最简单的方法。
答案4
与 的替代方式sed
。
为了N=1:
sed '$!N; /.*\n.*pattern/P; D' FILE
为了N=2
sed '1N; $!N; /.*\n.*\n.*pattern/P; D' FILE
为了N=2情况下,第一行将读取下一行N-1模式空间中的行然后开始一个N;P;D
循环 - 读取另一行,如果模式空间中的最后一行匹配,则打印模式空间中的第一行然后删除它,开始一个新的循环。
缺点是需要针对不同的值进行修改氮:
为了N=3:
sed '1{N;N}; $!N; /.*\n.*\n.*\n.*pattern/P; D' FILE
为了N=4:
sed '1{N;N;N}; $!N; /.*\n.*\n.*\n.*\n.*pattern/P; D' FILE
所以它很快就会变得很麻烦,尽管对于更大的值氮您可以准备一个脚本文件并将其传递给sed
。