2013-02-14 29 views
6

Tôi có một chuỗi regex python dài dòng (với nhiều khoảng trống và nhận xét) mà tôi muốn chuyển sang kiểu "bình thường" (để xuất sang javascript). Đặc biệt, tôi cần điều này khá đáng tin cậy. Nếu có cách nào đúng đắn để làm điều này, đó là điều tôi muốn. Ví dụ, việc triển khai ngây thơ sẽ phá hủy một regex như r' \# # A literal hash character', điều này không ổn.strip python verbose regex

Cách tốt nhất để làm điều này là ép buộc mô-đun trăn trở lại để cho tôi trở lại đại diện không chi tiết về regex của tôi, nhưng tôi không thấy cách nào để làm điều đó.

+2

Rõ ràng ai đó đã làm điều này, nhưng đó là trong JavaScript http://blog.mackerron.com/2010/08/08/extended-multi-line-js-regexps/ –

+0

Thật không may, nó chuyển đổi cú pháp regex chi tiết tùy chỉnh sang cú pháp JS regex, cú pháp này không hoàn toàn giống như việc chuyển đổi cú pháp regex của Python sang cú pháp Python không verbose… nhưng bạn chắc chắn có thể sử dụng mã đó như là một mô hình để viết Python tương đương của riêng bạn, nếu bạn không thể tìm thấy một – abarnert

+0

Điều này không nên quá khó. Chỉ cần xóa trước \ n nhưng trước một # và xóa mọi thứ khớp với \ w nhưng không khớp với \\\ w. – Linuxios

Trả lời

4

Tôi tin rằng bạn chỉ cần phải giải quyết hai vấn đề này để lột một regex verbose:

  1. xóa bình luận vào cuối dòng
  2. xóa khoảng trắng unescaped

thử loại này, mà chuỗi 2 với thay thế regex riêng biệt:

import re 

def unverbosify_regex_simple(verbose): 
    WS_RX = r'(?<!\\)((\\{2})*)\s+' 
    CM_RX = r'(?<!\\)((\\{2})*)#.*$(?m)' 

    return re.sub(WS_RX, "\\1", re.sub(CM_RX, "\\1", verbose)) 

Ở trên là một simplifie d phiên bản để lại các khoảng trống đã thoát. Kết quả đầu ra sẽ khó đọc hơn một chút nhưng sẽ hoạt động trên nền tảng regex.

Ngoài ra, đối với một câu trả lời hơi phức tạp hơn rằng "unescapes" không gian (ví dụ \ '=>' ') và trả về những gì tôi nghĩ hầu hết mọi người mong chờ:

import re 

def unverbosify_regex(verbose): 
    CM1_RX = r'(?<!\\)((\\{2})*)#.*$(?m)' 
    CM2_RX = r'(\\)?((\\{2})*)(#)' 
    WS_RX = r'(\\)?((\\{2})*)(\s)\s*' 

    def strip_escapes(match): 
     ## if even slashes: delete space and retain slashes 
     if (match.group(1) is None): 
     return match.group(2) 

     ## if number of slashes is odd: delete slash and keep space (or 'comment') 
     elif (match.group(1) == '\\'): 
     return match.group(2) + match.group(4) 

     ## error 
     else: 
     raise Exception 

    not_verbose_regex = re.sub(WS_RX, strip_escapes, 
         re.sub(CM2_RX, strip_escapes, 
         re.sub(CM1_RX, "\\1", 
          verbose))) 

    return not_verbose_regex 

UPDATE: thêm bình luận để giải thích ngay cả v. Đã sửa nhóm đầu tiên trong CM_RX để giữ lại toàn bộ 'nhận xét' nếu số lượng dấu gạch chéo là số lẻ.

CẬP NHẬT 2: Các nhận xét cố định regex, không xử lý các băm thoát đúng cách. Phải xử lý cả hai "# #cắt băm" cũng như "# nhận xét có \ # băm thoát" và "\\ # nhận xét"

CẬP NHẬT 3: Đã thêm phiên bản đơn giản, không dọn sạch các khoảng trống .

CẬP NHẬT 4: Tiếp tục đơn giản hóa để loại bỏ biến có độ dài lookbehind tiêu cực (và ngược lại/lừa ngược lại)

+0

Để cải thiện câu trả lời của bạn, bạn cũng có thể chuyển đổi ''\'' thành '''', ''\ #'' thành ''#''. – Ray

+0

Điểm 2 cần được sửa đổi thành trạng thái ", trừ khi xảy ra trong bộ" - điều này làm cho việc triển khai phức tạp hơn nhiều. – user4815162342

+0

Cảm ơn - câu trả lời được cập nhật để unescape không gian và băm. – dpkp