Text-Processing
在相鄰行上查找匹配項
我想找到相鄰的匹配行,例如,如果模式匹配是
$ grep -n pattern file1 file2 file3 file1:10: ... file2:100: ... file2:1000: ... file2:1001: ... file3:1: ... file3:123: ...
我想找到中間的兩個匹配項:
file2:1000: ... file2:1001: ...
但不是前兩個和後兩個。
我將使用與 thrig 相同的測試文件:
$ cat file a pat 1 pat 2 b pat 3
這是一個 awk 解決方案:
$ awk '/pat/ && last {print last; print} {last=""} /pat/{last=$0}' file pat 1 pat 2
這個怎麼運作
awk
隱式循環文件中的每一行。該程序使用一個變數 ,last
如果它與 regex 匹配,則該變數包含最後一行pat
。否則,它包含空字元串。
/pat/ && last {print last; print}
如果
pat
匹配此行和上一行,last
, 也是匹配,則列印這兩行。
{last=""}
替換
last
為空字元串
/pat/ {last=$0}
如果此行匹配
pat
,則設置last
為此行。這樣,當我們處理下一行時,它將可用。將> 2個連續匹配視為一組的替代方法
讓我們考慮這個擴展的測試文件:
$ cat file2 a pat 1 pat 2 b pat 3 c pat 4 pat 5 pat 6 d
與上面的解決方案不同,此程式碼將三個連續的匹配行視為一組要列印:
$ awk '/pat/{f++; if (f==2) print last; if (f>=2) print; last=$0; next} {f=0}' file2 pat 1 pat 2 pat 4 pat 5 pat 6
此程式碼使用兩個變數。和以前一樣,
last
是上一行。此外,f
計算連續匹配的次數。f
因此,我們在2 或更大時列印匹配行。添加類似 grep 的功能
為了模擬
grep
問題中顯示的輸出,此版本在每個匹配行之前列印文件名和行號:$ awk 'FNR==1{f=0} /pat/{f++; if (f==2) printf "%s:%s:%s\n",FILENAME,FNR-1,last; if (f>=2) printf "%s:%s:%s\n",FILENAME,FNR,$0; last=$0; next} {f=0}' file file2 file:2:pat 1 file:3:pat 2 file2:2:pat 1 file2:3:pat 2 file2:7:pat 4 file2:8:pat 5 file2:9:pat 6
awk 的 FILENAME 變數提供文件名,awk
FNR
提供文件中的行號。在每個文件的開頭
FNR==1
,我們重置f
為零。這可以防止一個文件的最後一行被認為與下一個文件的第一行是連續的。對於那些喜歡他們的程式碼分佈在多行的人來說,上面看起來像:
awk ' FNR==1{f=0} /pat/ {f++ if (f==2) printf "%s:%s:%s\n",FILENAME,FNR-1,last if (f>=2) printf "%s:%s:%s\n",FILENAME,FNR,$0 last=$0 next } {f=0} ' file file2