2010-04-13 26 views
6

Tôi khá kinh nghiệm với Perl và Ruby nhưng mới với Python vì vậy tôi hy vọng ai đó có thể chỉ cho tôi cách Pythonic để hoàn thành nhiệm vụ sau. Tôi muốn so sánh một số dòng với nhiều biểu thức chính quy và truy xuất nhóm phù hợp. Trong Ruby nó sẽ là một cái gì đó như thế này:Python so sánh chuỗi với một số biểu thức chính quy

# Revised to show variance in regex and related action. 
data, foo, bar = [], nil, nil 
input_lines.each do |line| 
    if line =~ /Foo(\d+)/ 
    foo = $1.to_i 
    elsif line =~ /Bar=(.*)$/ 
    bar = $1 
    elsif bar 
    data.push(line.to_f) 
    end 
end 

nỗ lực của tôi trong Python đang chuyển ra khá xấu xí vì nhóm phù hợp được trả về từ một cuộc gọi để phù hợp/tìm kiếm trên một biểu thức chính quy và Python không có nhiệm vụ trong điều kiện hoặc báo cáo chuyển đổi. Cách Pythonic để làm gì (hoặc suy nghĩ!) Về vấn đề này?

+1

Xem http://stackoverflow.com/questions/2554185/match-groups-in-python. – PaulMcG

+0

Vâng, câu hỏi đó là những gì tôi đang tìm kiếm - cảm ơn! – maerics

Trả lời

0

Paul McGuire's solution của việc sử dụng một lớp trung gian REMatcher mà thực hiện trận đấu, lưu trữ các nhóm phù hợp, và trả về một boolean cho sự thành công/thất bại hóa ra để sản xuất mã dễ đọc nhất cho mục đích này.

1

Something như thế này, nhưng đẹp hơn:

regexs = [re.compile('...'), ...] 

for regex in regexes: 
    m = regex.match(s) 
    if m: 
    print m.groups() 
    break 
else: 
    print 'No match' 
+1

Tôi đã thử một cái gì đó tương tự nhưng tôi muốn thực hiện các hành động khác nhau dựa trên đó regex phù hợp, vì vậy tôi di chuyển từ một danh sách để một từ điển lập bản đồ regexs để lambdas được gọi là nếu phù hợp được tìm thấy nhưng nó làm cho một số mã khó hiểu ... – maerics

1

Có một số cách để "ràng buộc một tên on the fly" bằng Python, như cũ recipe của tôi cho "gán và kiểm tra"; trong trường hợp này tôi có thể chọn một cách khác như vậy (giả sử Python 2.6, cần một số thay đổi nhỏ nếu bạn đang làm việc với phiên bản cũ của Python), giống như:

import re 
pats_marks = (r'^A:(.*)$', 'FOO'), (r'^B:(.*)$', 'BAR') 
for line in lines: 
    mo, m = next(((mo, m) for p, m in pats_mark for mo in [re.match(p, line)] if mo), 
       (None, None)) 
    if mo: print '%s: %s' % (m, mo.group(1)) 
    else: print 'NO MATCH: %s' % line 

Nhiều chi tiết nhỏ có thể được điều chỉnh, tất nhiên (ví dụ, tôi chỉ chọn (.*) thay vì (.*?) làm nhóm phù hợp - chúng tương đương với $ ngay lập tức vì vậy tôi đã chọn biểu mẫu ngắn hơn ;-) - bạn có thể biên dịch trước REs, so với số pats_mark tuple (ví dụ: với dict được lập chỉ mục theo mẫu RE), v.v.

Nhưng ý tưởng đáng kể, tôi nghĩ, là làm cho ructure data-driven, và liên kết đối tượng khớp với tên trên bay với subexpression for mo in [re.match(p, line)], một "vòng lặp" trên một danh sách đơn (genexps liên kết các tên chỉ bằng vòng lặp, không phải bằng cách gán - một số xem xét sử dụng phần này các thông số kỹ thuật của genexps là "khéo léo", nhưng tôi coi nó là một thành ngữ Python hoàn toàn có thể chấp nhận được, đặc biệt là. kể từ khi nó được xem xét trở lại trong thời gian khi danh sách, tổ tiên của "genexps" trong một ý nghĩa, đã được thiết kế).

-1

regex của bạn chỉ đơn giản là lấy bất kỳ thứ gì sau ký tự thứ 3 trở đi.

for line in open("file"): 
    if line.startswith("A:"): 
     print "FOO #{"+line[2:]+"}" 
    elif line.startswith("B:"): 
     print "BAR #{"+line[2:]+"}" 
    else: 
     print "No match" 
+0

cách tốt đẹp, nhưng tôi muốn sử dụng tách và so sánh: bắt đầu, rest = line.split (':', 1) nếu bắt đầu == "A": v.v ... – moshez

+0

Điều này là tốt nhưng tôi tìm kiếm một cái gì đó tổng quát hơn, regex đơn giản chỉ dành cho mục đích giải thích, các regex thực tế sẽ khá phức tạp. – maerics

Các vấn đề liên quan