2012-02-03 29 views
27

Đối với làm một regex thay thế, có ba điều mà bạn cung cấp cho nó:Regex trong python: là nó có thể để có được phù hợp, thay thế, và chuỗi cuối cùng?

  • Các mô hình phù hợp
  • Các mô hình thay thế
  • Chuỗi gốc

Có ba điều mà động cơ regex mà tôi quan tâm:

  • Kết hợp chuỗi
  • Việc thay thế chuỗi
  • Các thức xử lý chuỗi

Khi sử dụng re.sub, chuỗi thức là những gì trả lại. Nhưng có thể truy cập hai thứ khác, chuỗi và chuỗi thay thế được kết hợp không?

Dưới đây là một ví dụ:

orig = "This is the original string." 
matchpat = "(orig.*?l)" 
replacepat = "not the \\1" 

final = re.sub(matchpat, replacepat, orig) 
print(final) 
# This is the not the original string 

Chuỗi trận đấu là "original" và chuỗi thay thế là "not the original". Có cách nào để lấy chúng không? Tôi đang viết một kịch bản để tìm kiếm và thay thế trong nhiều tập tin, và tôi muốn nó để in nó những gì nó tìm kiếm và thay thế, mà không cần in ra toàn bộ dòng.

+0

Tôi đã tự hỏi điều này một lúc. Câu hỏi hay! – Blender

+0

Câu hỏi rất hay. Và được bào chế rất tốt. +1 – ovgolovin

Trả lời

26
class Replacement(object): 

    def __init__(self, replacement): 
     self.replacement = replacement 
     self.matched = None 
     self.replaced = None 

    def __call__(self, match): 
     self.matched = match.group(0) 
     self.replaced = match.expand(self.replacement) 
     return self.replaced 

>>> repl = Replacement('not the \\1') 
>>> re.sub('(orig.*?l)', repl, 'This is the original string.') 
    'This is the not the original string.' 
>>> repl.matched 
    'original' 
>>> repl.replaced 
    'not the original' 

Chỉnh sửa: vì @FJ có chỉ ra, ở trên sẽ chỉ nhớ trận đấu/thay thế cuối cùng. Phiên bản này xử lý nhiều lần xuất hiện:

class Replacement(object): 

    def __init__(self, replacement): 
     self.replacement = replacement 
     self.occurrences = [] 

    def __call__(self, match): 
     matched = match.group(0) 
     replaced = match.expand(self.replacement) 
     self.occurrences.append((matched, replaced)) 
     return replaced 

>>> repl = Replacement('[\\1]') 
>>> re.sub('\s(\d)', repl, '1 2 3') 
    '1[2][3]' 

>>> for matched, replaced in repl.occurrences: 
    ....:  print matched, '=>', replaced 
    ....:  
2 => [2] 
3 => [3] 
+1

+1: Đẹp hơn nhiều so với giải pháp của tôi. Tôi sẽ ăn cắp mã này. – Blender

+0

Điều này sẽ chỉ lưu trữ kết quả phù hợp và thay thế cuối cùng, nhưng sẽ không khó để biến các biến mẫu 'matched' và' replace' thành các danh sách để giữ tất cả chúng. –

+1

+1 để chuyển một lớp có thể gọi được, nơi mọi người thường sử dụng các chức năng. Tài giỏi. – twneale

9

tôi nhìn vào tài liệu và nó có vẻ như bạn có thể vượt qua một tài liệu tham khảo chức năng vào re.sub:

import re 

def re_sub_verbose(pattern, replace, string): 
    def substitute(match): 
    print 'Matched:', match.group(0) 
    print 'Replacing with:', match.expand(replace) 

    return match.expand(replace) 

    result = re.sub(pattern, substitute, string) 
    print 'Final string:', result 

    return result 

Và tôi nhận ra điều này khi chạy re_sub_verbose("(orig.*?l)", "not the \\1", "This is the original string."):

Matched: original 
Replacing with: not the original 
This is the not the original string. 
+1

+1, tôi đã ở giữa viết lên cùng một điều –

+0

Tôi chỉ không thể tìm ra cách để làm cho nó đẹp để nó hoạt động cho các regex khác, như tôi đang sử dụng điều này trong mã của riêng tôi: P – Blender

+2

Bạn cũng có thể gọi 'match.expand ('không phải \\ 1')' (http://docs.python.org/library/re.html#re.MatchObject.expand) –

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