2011-11-19 12 views
6

Chcę mieć wyrażenie regularne, które wyszukuje teksty, które są "zapakowane" pomiędzy "HEAD lub HEADa" i "HEAD." Oznacza to, że mogę mieć tekst, który zaczyna się od pierwszego słowo jako szef lub HEADa oraz następujące „głowy” są typu HEAD.Python regex ze spojrzeniem w tył i alternatywami

  1. HEAD\n\n text...text...HEAD \n\n text....text HEAD\n\n text....text .....
  2. HEADa\n\n text...text...HEAD \n\n text....text HEAD\n\n text....text .....

Chcę tylko, aby uchwycić tekstowe, które są pomiędzy „głowy” więc ja miej regex z patrzeniem w tył i patrz ahea d wyrażenia szukające moich "głów". Mam następujące wyrażenia regularnego:

var = "HEADa", "HEAD" 

my_pat = re.compile(r"(?<=^\b"+var[0]+r"|"+var[1]+r"\b) \w*\s\s(.*?)(?=\b"+var[1] +r"\b)",re.DOTALL|re.MULTILINE) 

Jednak, gdy próbuję wykonać ten regex, otrzymuję komunikat o błędzie, że nie mogę mieć zmienną długość w wyglądzie za wypowiedzi. Co jest nie tak z tym regex?

+0

Podziękowania dla Chrisa Morgana, o wiele łatwiejsze do odczytania. – user963386

+0

Przy okazji powinieneś również zaakceptować odpowiedzi na swoje pozostałe pytania. – FailedDev

Odpowiedz

14

Obecnie pierwsza część regex wygląda następująco:

(?<=^\bHEADa|HEAD\b) 

Masz dwie alternatywy; jeden dopasowuje pięć znaków, a drugi dopasowuje cztery, i dlatego pojawia się błąd. Niektóre smaki regex pozwolą ci to zrobić, nawet jeśli mówią, że nie zezwalają na zmienne style, ale nie na Python. Ci mógłby podzielić ją na dwie lookbehinds, tak:

(?:(?<=^HEADa\b)|(?<=\bHEAD\b)) 

... ale pewnie nie trzeba lookbehinds za to w każdym razie. Spróbuj to zamiast:

(?:^HEADa|\bHEAD)\b 

Cokolwiek zostanie dopasowane przez (.*?) później nadal będą dostępne za pośrednictwem grupa nr 1. Jeśli naprawdę potrzebujesz całego tekstu między ogranicznikami, możesz przechwycić , że w grupie # 1, a ta inna grupa stanie się # 2 (lub możesz użyć nazwanych grup i nie musisz śledzić liczb) .

Ogólnie rzecz biorąc, lookbehind nigdy nie powinno być Twoją pierwszą ucieczką. Może się wydawać, że jest to oczywiste narzędzie do wykonania zadania, ale zazwyczaj lepiej jest wykonać proste dopasowanie i wyodrębnić pożądaną część za pomocą grupy przechwytującej. Dotyczy to wszystkich smaków, nie tylko Pythona; tylko dlatego, że można zrobić więcej z Lookbehinds w innych smakach, nie oznacza, że ​​powinien.

BTW, być może zauważyłeś, że redystrybuowałem Twoje granice słów; Myślę, że tak właśnie zamierzałeś.

+0

Dostałeś mnie do rzeczy :) +1. Dodatkowo możesz interpolować zmienną w następujący sposób: ** regex = re.compile ('(? <=^\ B% s |% s \ b) \ w * \ s \ s (. *?) (? = \ b% s \ b) "% (var [0], var [1], var [1]), re.DOTALL | re.MULTILINE) ** – FailedDev

+0

Podziękowania dla Allana Moore'a za bardzo dobre wyjaśnienie – user963386