仅在与模式匹配的每一行之前打印第 N 行

ram*_*ran 5 awk search text-processing

我试图<N>在搜索模式之前只打印第 th 行。grep -B<N>打印<N>搜索模式之前的所有行。我在这里看到了 awk 代码它只能打印<N>搜索模式后的第 th 行。

awk 'c&&!--c;/pattern/{c=N}' file
Run Code Online (Sandbox Code Playgroud)

如何修改它以仅在<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  
...
Run Code Online (Sandbox Code Playgroud)

我需要一个可以返回2nd line搜索字符串之前的命令Direct configuration。我正在尝试在SUSE-Linux 中运行它

Jay*_*got 11

需要使用行缓冲区。

试试这个:

awk -v N=4 -v pattern="example.*pattern" '{i=(1+(i%N));if (buffer[i]&& $0 ~ pattern) print buffer[i]; buffer[i]=$0;}' file
Run Code Online (Sandbox Code Playgroud)

N值设置为要打印的图案之前的第 N 行。

pattern值设置为要搜索的正则表达式。

buffer是一个N元素数组。它用于存储行。每次找到N图案时,都会打印图案之前的第 th 行。


ter*_*don 8

该代码不适用于前几行。要在匹配模式之前获取行,您需要以某种方式保存已处理的行。由于awk只有关联数组,我想不出一个同样简单的方法来做你想做的事情awk,所以这里有一个 perl 解决方案:

perl -ne 'push @lines,$_; print $lines[0] if /PAT/; shift(@lines) if $.>LIM;' file 
Run Code Online (Sandbox Code Playgroud)

更改PAT为要匹配的模式和LIM行数。例如,要在每次出现 之前打印第 5 行foo,您可以运行:

perl -ne 'push @lines,$_; print $lines[0] if /foo/; shift(@lines) if $.>5;' file 
Run Code Online (Sandbox Code Playgroud)

解释

  • perl -ne: 逐行读取输入文件并将给出的脚本应用-e到每一行。
  • push @lines,$_: 将当前行 ( $_)添加到数组中@lines
  • print $lines[0] if /PAT/:如果当前行与所需模式匹配,则打印数组中的第一个元素@lines( $lines[0])。
  • shift(@lines) if $.>LIM;:$.是当前行号。如果大于限制,则从数组中删除第一个值@lines。结果是@lines总是有最后LIM几行。

  • @terdon `awk` 确实提出了 _classic_ 数组。看看我的回答。 (2认同)