W mojej aplikacji Pythona, muszę napisać wyrażenie regularne, które pasuje do C++ for
lub while
pętlę, która została rozwiązana ze średnikiem (;
). Na przykład, należy dopasować to:Wyrażenie regularne do wykrywania średnik zakończony C++ dla & przy jednoczesnym pętle
for (int i = 0; i < 10; i++);
... ale nie w ten sposób:
for (int i = 0; i < 10; i++)
To wygląda na pierwszy rzut oka banalne, dopóki nie uświadomimy sobie, że tekst pomiędzy otwarciem i zamknięciem nawiasu mogą zawierać inny nawias, na przykład:
for (int i = funcA(); i < funcB(); i++);
Używam modułu python.re. Teraz moje wyrażenie regularne wygląda następująco (Zostawiłam moje komentarze w tak można go zrozumieć łatwiej):
# match any line that begins with a "for" or "while" statement:
^\s*(for|while)\s*
\( # match the initial opening parenthesis
# Now make a named group 'balanced' which matches a balanced substring.
(?P<balanced>
# A balanced substring is either something that is not a parenthesis:
[^()]
| # …or a parenthesised string:
\(# A parenthesised string begins with an opening parenthesis
(?P=balanced)* # …followed by a sequence of balanced substrings
\) # …and ends with a closing parenthesis
)* # Look for a sequence of balanced substrings
\) # Finally, the outer closing parenthesis.
# must end with a semi-colon to match:
\s*;\s*
Działa to doskonale dla wszystkich powyższych przypadkach, ale zrywa jak najszybciej spróbować zrobić trzecia część pętli for zawierać funkcję tak:
for (int i = 0; i < 10; doSomethingTo(i));
myślę, że łamie bo tak szybko, jak można umieścić tekst pomiędzy otwierającym i zamykającym nawiasie, grupa „zrównoważony” pasuje który zawierał tekst, a zatem część (?P=balanced)
nie działa już więcej, ponieważ nie będzie pasować (ze względu na fakt, że tekst wewnątrz nawiasów jest inny).
W moim kodu Pythona Używam gadatliwym i multilinii flagi i tworzenia wyrażenia regularnego tak:
REGEX_STR = r"""# match any line that begins with a "for" or "while" statement:
^\s*(for|while)\s*
\( # match the initial opening parenthesis
# Now make a named group 'balanced' which matches
# a balanced substring.
(?P<balanced>
# A balanced substring is either something that is not a parenthesis:
[^()]
| # …or a parenthesised string:
\(# A parenthesised string begins with an opening parenthesis
(?P=balanced)* # …followed by a sequence of balanced substrings
\) # …and ends with a closing parenthesis
)* # Look for a sequence of balanced substrings
\) # Finally, the outer closing parenthesis.
# must end with a semi-colon to match:
\s*;\s*"""
REGEX_OBJ = re.compile(REGEX_STR, re.MULTILINE| re.VERBOSE)
Może ktoś sugerują poprawę do tego wyrażenia regularnego? To zbyt skomplikowane, żebym się obrócił.
Dzięki - myślę, że wyrazy regularne naprawdę są niewłaściwym narzędziem do pracy! – Thomi
Należy również wziąć pod uwagę komentarze i łańcuchy, które rzucają ten algorytm. –
Możesz wcześniej usunąć komentarze i ciągi za pomocą wyrażenia regularnego. :) Lub wprowadzić więcej zmiennych, takich jak openBr, które wskazują, czy jesteś wewnątrz komentarza (i jakiego typu komentarz, więc wiesz, co zamyka go) lub ciąg. – Frank