2011-09-22 20 views
5

次のテキストパターンを考慮して、Python - single対multiline REGEX

#goals:プロセスレポートのタイムスタンプ、たとえば、 2011-09-21 15:45:00とsuccの最初の2つの統計。統計行、例えば:

input_text = ''' 
# Process_Name  (23387) Report at 2011-09-21 15:45:00.001 Type: Periodic #\n 
some line 1\n 
some line 2\n 
some other lines\n 
succ. statistics |  1438  1439 99 | 3782245 3797376 99 |\n 
some lines\n 
Process_Name  (23387) Report at 2011-09-21 15:50:00.001 Type: Periodic #\n 
some line 1\n 
some line 2\n 
some other lines\n 
succ. statistics |  1436  1440 99 | 3782459 3797523 99 |\n 
repeat the pattern several hundred times... 
''' 

行に行を反復するとき、私はそれが働いてしまった、

def parse_file(file_handler, patterns): 

    results = [] 
    for line in file_handler: 
     for key in patterns.iterkeys(): 
      result = re.match(patterns[key], line) 
      if result: 
       results.append(result) 

return results 

patterns = { 
    'report_date_time': re.compile('^# Process_Name\s*\(\s*\d+\) Report at (.*)\.[0-9] {3}\s+Type:\s*Periodic\s*#\s*.*$'), 
    'serv_term_stats': re.compile('^succ. statistics \|\s+(\d+)\s+ (\d+)+\s+\d+\s+\|\s+\d+\s+\d+\s+\d+\s+\|\s*$'), 
    } 
results = parse_file(fh, patterns) 

[('2011-09-21 15:40:00',), 
('1425', '1428'), 
('2011-09-21 15:45:00',), 
('1438', '1439')] 

を返すが、私のようタプル出力のリストを持ちます目標、

[('2011-09-21 15:40:00','1425', '1428'), 
('2011-09-21 15:45:00', '1438', '1439')] 

私は、最初のパターンとそれらの間の怠惰な数量詞で、いくつかのコンボを試してみましたが、私はこれを実現するにはどうすればよい複数行のREGEX

# .+? Lazy quantifier "match as few characters as possible (all characters allowed) until reaching the next expression" 
pattern = '# Process_Name\s*\(\s*\d+\) Report at (.*)\.[0-9]{3}\s+Type:\s*Periodic.*?succ. statistics) \|\s+(\d+)\s+(\d+)+\s+\d+\s+\|\s+\d+\s+\d+\s+\d+\s+\|\s' 
regex = re.compile(pattern, flags=re.MULTILINE) 

data = file_handler.read()  
for match in regex.finditer(data): 
    results = match.groups() 

を使用してパターンをキャプチャする方法を見つけ出すことはできませんか?

+0

私はあなたのための答えを持っていないのが、なぜあなたはそのような複数行の文字列に\ nを埋め込んでいますか?文字列の実際の改行は改行です。 – geoffspear

+0

右Wooble、これはLinux上にあるので、改行文字を表現するために追加されています(通常は\ nまたは\ rまたは\ r \ nですか?) –

答えて

8

使用re.DOTALLので.は改行を含む任意の文字にマッチします:

import re 

data = ''' 
# Process_Name  (23387) Report at 2011-09-21 15:45:00.001 Type: Periodic #\n 
some line 1\n 
some line 2\n 
some other lines\n 
succ. statistics |  1438  1439 99 | 3782245 3797376 99 |\n 
some lines\n 
repeat the pattern several hundred times... 
''' 

pattern = r'(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}).*?succ. statistics\s+\|\s+(\d+)\s+(\d+)' 
regex = re.compile(pattern, flags=re.MULTILINE|re.DOTALL) 

for match in regex.finditer(data): 
    results = match.groups() 
    print(results) 

    # ('2011-09-21', '1438', '1439') 
+0

Wow。あなたは高速です。答えとunutbuの改善のおかげで、あなたのような指導者のためのおかげでstackoverflow! –

+0

編集:マイナーなバンプ、私は非貪欲な量指定子を保証する必要があります。そうでなければ正規表現は最初のタイムスタンプ、最後の統計情報をキャプチャし、その間の1000個の+ラインは無視します。したがって、パターン= r '(\ d {4} - \ d {2} - \ d {2} \ d {2}:\ d {2}:\ d {2})。統計\ s + \ | \ s +(\ d +)\ s +(\ d +) ' –

+0

@JoaoFigueiredo:ああ良い点。訂正してくれてありがとう。 – unutbu