匹配patternA並僅在patternB匹配時列印它,包括以下行

匹配patternA並僅在patternB匹配時列印它,包括以下行

我希望獲取所有包含“search_string”一詞的行+其後的行+其前匹配“mod”的行。
我試過:

grep -n 'mod\|search_string' ip | grep --before 1 search_string> inter  
grep -n --after 1 search_string ip >> inter  
sort -t':' -k1,1n -u inter -o op

有沒有更好的辦法?

文件:

mod start1  
some lines  
mod start2  
other lines  
mod start3  
 many other lines  
 search_string yada yada  
 hello  
 many other lines  
 search_string yada yada  
 bye  
mod start4  
 search_string baba baba  
 this too  
mod start5  

預期輸出:

mod start3  
 search_string yada yada   
 hello  
 search_string yada yada  
 bye  
mod start4  
 search_string baba baba  
 this too

答案1

awk '
   $0 ~ /mod/ { md=$0 }
   $0 ~ /search_string/ { if(md!="") { print md }; md="" ; print; getline; print }
   '

解釋:

  • 包含的行mod另存為md.
  • search_string包含觸發列印先前儲存的行md、該行本身和下一行的行。
  • if(md!="")md=""確保當單一(在您的範例中)下mod有多個 -s 時不會出現重複行。search_stringmodmod start3

筆記:

  • mod包含和的行將search_string打破這個邏輯。

答案2

您的文件包含“回車”字元。最好在 Unix 中刪除它們。若要列印您發布的命令序列(刪除回車符),請嘗試:

awk '{gsub(/\r/,"")}
     /mod/          { a = $0 }
     /search_string/{ if(a!=""){print(a);a=""}
                      print;getline;print
                    }
    ' infile

或作為一句單行:

$ awk '{gsub(/\r/,"")}/mod/{a=$0}/search_string/{if(a!=""){print(a);a=""}print;getline;print}' infile

mod start3  
 search_string yada yada  
 hello  
 search_string yada yada  
 bye  
mod start4  
 search_string baba baba  
 this too  

由於可以在 (GNU) awk 中使用多字元記錄分隔符,我們可以將記錄分隔符設為mod並僅列印包含search_string.需要 printf 來重建原始記錄。

若要列印您發佈為「預期輸出」的內容,請嘗試:

awk '/search_string/{printf("mod%s", $0)}' RS=mod infile

答案3

如果您想在 Python 腳本中執行此操作:

# Read file into memory.
with open('myfile.txt') as f:
    lines = [line.rstrip() for line in f]

# Loops through lines backwards, looking for string and optionally mod.
output_lines = list()
find_mod = False
for i, line in enumerate(lines[::-1]):
    if 'search_string' in line:
        output_lines.append(lines[::-1][i-1])
        output_lines.append(lines[::-1][i])
        find_mod = True
    elif find_mod and 'mod' in line:
        output_lines.append(lines[::-1][i])
        find_mod=False

print("\n".join(output_lines[::-1]))

相關內容