
我試圖僅列印<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
.