2013-02-14 14 views
6

Mam vergese python ciąg regex (z dużą ilością białych znaków i komentarzy), które chciałbym przekonwertować na "normalny" styl (do eksportu do javascript). W szczególności potrzebuję tego, aby był całkiem niezawodny. Jeśli istnieje jakaś poprawna metoda robienia tego, to właśnie tego chcę. Na przykład naiwna implementacja zniszczyłaby wyrażenie regularne takie jak r' \# # A literal hash character', co nie jest poprawne.strip verbose python regex

Najlepszym sposobem na zrobienie tego byłoby zmusić moduł python re do przekazania mi nieskończonej reprezentacji mojego regex, ale nie widzę sposobu, aby to zrobić.

+2

Najwyraźniej ktoś to zrobił, ale to w JavaScript http://blog.mackerron.com/2010/08/08/extended-multi-line-js-regexps/ –

+0

Niestety, konwertuje niestandardową składnię wyrażeń regularnych do składni regex JS, co nie jest całkiem takie samo, jak konwersja pełnej składni wyrażeń regularnych Pythona do niewerbalnej składni wyrażeń regularnych w języku Python ... ale możesz zdecydowanie użyć tego kodu jako modelu do pisania własnego odpowiednika w Pythonie, jeśli nie możesz znaleźć takiego kodu. – abarnert

+0

To nie powinno być zbyt trudne. Po prostu usuń przed \ n, ale przed #, i usuń wszystko, co pasuje \ w, ale nie \\\ w. – Linuxios

Odpowiedz

4

wierzę, trzeba tylko rozwiązać te dwa problemy rozebrać się pełny regex:

  1. usuwania komentarzy do końca linii
  2. usuwać Niecytowany białymi

spróbować tego, co łańcuchy 2 z osobnymi podstawieniami wyrażeń regularnych:

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)) 

Powyższe jest uproszczone d wersja, która pozostawia spacje z ewidencją, tak jak jest. Wynikowy wynik będzie nieco trudniejszy do odczytania, ale powinien działać na platformach regex.

Alternatywnie, na nieco bardziej złożoną odpowiedź, że "unescapes" obowiązuje (czyli '\' => ' „) i zwraca to, co myślę, że większość ludzi będzie oczekiwać:

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: dodany komentarze, aby wyjaśnić nawet v. dziwne zliczanie slashów. Naprawiono pierwszą grupę w CM_RX, aby zachować pełny "komentarz", jeśli liczba slasha jest nieparzysta.

AKTUALIZACJA 2: Naprawiono komentarze regex, które nie zajmowały się odpowiednio hasłami z hasłami. Powinien obsługiwać zarówno "\ # #escaped hash" oraz "# komentarz # uciekł z \ hash" i "\\ # comment"

UPDATE 3: Dodany uproszczona wersja, która nie oczyścić przestrzenie uciekli .

UPDATE 4: Dalsze uproszczenie wyeliminowanie zmiennej długości negatywny lookbehind (i do tyłu/odwrotną sztuczki)

+0

Aby poprawić odpowiedź, możesz również przekonwertować ''\'' na '''', ''\ #'' na ''#''. – Ray

+0

Punkt 2 powinien zostać zmieniony tak, aby stanowił "z wyjątkiem sytuacji, gdy występuje w zestawach" - co sprawia, że ​​realizacja jest znacznie bardziej złożona. – user4815162342

+0

Dzięki - odpowiedź została zaktualizowana, aby unescape the spaces and hashe. – dpkp