「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_string
mod
mod start3
メモ:
mod
とを含む行はsearch_string
このロジックを破ります。
答え2
ファイルに「キャリッジリターン」文字が含まれています。 Unixでは削除するのが最善です。発行したコマンドシーケンスを印刷するには(キャリッジリターンを削除する)、次の手順を試してください。
awk '{gsub(/\r/,"")}
/mod/ { a = $0 }
/search_string/{ if(a!=""){print(a);a=""}
print;getline;print
}
' infile
または1行で:
$ 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
レコードを再構成するにはprintfのみがsearch_string
必要です。
投稿した内容を「予想出力」として印刷するには、次の手順を試してください。
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]))