Pythonでファイル内文字列検索!grep的処理で特定行を抽出する方法
Pythonでファイル内の特定文字列を含む行を抽出する処理は、ログ解析やデータ処理で頻繁に使用されます。本記事では、Unix/Linuxのgrepコマンドのような機能をPythonで実現する方法を詳しく解説します。
基本的な文字列検索・抽出
特定文字列を含む行の抽出
# ファイルから特定文字列を含む行を抽出
def grep_lines(filename, search_text):
with open(filename, 'r', encoding='utf-8') as f:
for line_num, line in enumerate(f, 1):
if search_text in line:
print(f'{line_num}: {line.strip()}')
# 使用例
grep_lines('log.txt', 'ERROR')
抽出結果をリストで取得
def find_matching_lines(filename, search_text):
matches = []
with open(filename, 'r', encoding='utf-8') as f:
for line_num, line in enumerate(f, 1):
if search_text in line:
matches.append({'line_num': line_num, 'content': line.strip()})
return matches
# 使用例
results = find_matching_lines('data.txt', 'Python')
for result in results:
print(f"行 {result['line_num']}: {result['content']}")
正規表現を使った高度な検索
正規表現パターンマッチング
import re
def grep_regex(filename, pattern):
regex = re.compile(pattern)
with open(filename, 'r', encoding='utf-8') as f:
for line_num, line in enumerate(f, 1):
if regex.search(line):
print(f'{line_num}: {line.strip()}')
# IPアドレスを含む行を検索
grep_regex('access.log', r'\d+\.\d+\.\d+\.\d+')
大文字小文字を区別しない検索
import re
def case_insensitive_grep(filename, search_text):
pattern = re.compile(search_text, re.IGNORECASE)
with open(filename, 'r', encoding='utf-8') as f:
for line_num, line in enumerate(f, 1):
if pattern.search(line):
print(f'{line_num}: {line.strip()}')
# 使用例
case_insensitive_grep('text.txt', 'error')
複数条件での検索
AND条件(複数キーワードすべてを含む)
def grep_all_keywords(filename, keywords):
with open(filename, 'r', encoding='utf-8') as f:
for line_num, line in enumerate(f, 1):
if all(keyword in line for keyword in keywords):
print(f'{line_num}: {line.strip()}')
# 'ERROR'と'database'両方を含む行を検索
grep_all_keywords('app.log', ['ERROR', 'database'])
OR条件(いずれかのキーワードを含む)
def grep_any_keywords(filename, keywords):
with open(filename, 'r', encoding='utf-8') as f:
for line_num, line in enumerate(f, 1):
if any(keyword in line for keyword in keywords):
print(f'{line_num}: {line.strip()}')
# 'ERROR'または'WARNING'を含む行を検索
grep_any_keywords('app.log', ['ERROR', 'WARNING'])
実践的な使用例
ログファイル解析
from datetime import datetime
def analyze_log(filename, error_level='ERROR'):
error_count = 0
errors = []
with open(filename, 'r', encoding='utf-8') as f:
for line_num, line in enumerate(f, 1):
if error_level in line:
error_count += 1
errors.append({
'line': line_num,
'content': line.strip(),
'timestamp': line.split()[0] if line.split() else 'N/A'
})
print(f'{error_level}レベルのエントリ: {error_count}件')
return errors
# エラーログの解析
errors = analyze_log('application.log', 'ERROR')
CSVファイルの特定条件抽出
import csv
def grep_csv(filename, column_name, search_value):
matches = []
with open(filename, 'r', encoding='utf-8') as f:
reader = csv.DictReader(f)
for row_num, row in enumerate(reader, 2): # ヘッダー行の次から
if search_value in str(row.get(column_name, '')):
matches.append({'row': row_num, 'data': row})
return matches
# 名前列に'田中'を含む行を検索
results = grep_csv('users.csv', '名前', '田中')
高性能な大容量ファイル処理
メモリ効率的な検索
def efficient_grep(filename, search_text, max_results=None):
count = 0
with open(filename, 'r', encoding='utf-8') as f:
for line_num, line in enumerate(f, 1):
if search_text in line:
yield {'line_num': line_num, 'content': line.strip()}
count += 1
if max_results and count >= max_results:
break
# 最初の10件のみ取得
for match in efficient_grep('large_file.txt', 'keyword', max_results=10):
print(f"行 {match['line_num']}: {match['content']}")
結果の保存
検索結果をファイルに出力
def grep_to_file(input_file, output_file, search_text):
match_count = 0
with open(input_file, 'r', encoding='utf-8') as infile, \
open(output_file, 'w', encoding='utf-8') as outfile:
for line_num, line in enumerate(infile, 1):
if search_text in line:
outfile.write(f'{line_num}: {line}')
match_count += 1
print(f'{match_count}行を{output_file}に出力しました')
# 検索結果をファイルに保存
grep_to_file('input.log', 'errors.txt', 'ERROR')
pathlib.Pathを使った現代的なアプローチ
from pathlib import Path
def modern_grep(file_path, search_text):
path = Path(file_path)
if not path.exists():
print(f'ファイルが見つかりません: {file_path}')
return []
lines = path.read_text(encoding='utf-8').splitlines()
matches = []
for line_num, line in enumerate(lines, 1):
if search_text in line:
matches.append({'line_num': line_num, 'content': line})
return matches
# 使用例
results = modern_grep('data.txt', 'Python')
まとめ
Pythonでファイル内の文字列検索を行う際は、基本的なin演算子から正規表現まで、用途に応じて適切な手法を選択することが重要です。大容量ファイルの処理では、メモリ効率を考慮したジェネレータを使用し、複雑な条件での検索には正規表現を活用することで、柔軟で高性能なgrep的処理が実現できます。
■プロンプトだけでオリジナルアプリを開発・公開してみた!!
■AI時代の第一歩!「AI駆動開発コース」はじめました!
テックジム東京本校で先行開始。
■テックジム東京本校
「武田塾」のプログラミング版といえば「テックジム」。
講義動画なし、教科書なし。「進捗管理とコーチング」で効率学習。
より早く、より安く、しかも対面型のプログラミングスクールです。
<短期講習>5日で5万円の「Pythonミニキャンプ」開催中。
<月1開催>放送作家による映像ディレクター養成講座
<オンライン無料>ゼロから始めるPython爆速講座



