2.35. Podstawy wzorców¶
Wyrażenie regularne to mały język służący do opisywania łańcuchów według ich formy, a nie dokładnej zawartości. Użyj go, gdy łańcuch pasuje wtedy i tylko wtedy, gdy spełnia wzorzec, który potrafisz opisać, ale nie potrafisz wyliczyć – „ciąg cyfr, po którym następuje jednostka”, „wiersz zaczynający się od ERROR i kończący liczbą”, „dowolne z tych rozszerzeń plików, w dowolnej kolejności, z opcjonalnymi przedrostkami v„.
Sięgaj po re tylko wtedy, gdy zwykła metoda łańcucha nie wystarczy.
str.startswith(),str.endswith()– sprawdzanie stałego przedrostka lub przyrostka.in– sprawdzanie, czy obecny jest stały podłańcuch.str.split(),str.find(),str.replace()– praca ze stałymi ogranicznikami.
Każda z nich jest szybsza, łatwiejsza do odczytania i trudniejsza do popsucia niż odpowiadające jej wyrażenie regularne. Używaj wyrażeń regularnych, gdy liczy się forma łańcucha, a dokładny podłańcuch nie.
2.35.1. Cztery rzeczy, których będziesz używać¶
Moduł re w MicroPython udostępnia cztery rzeczy:
re.compile()– zamienia łańcuch wzorca w skompilowany obiekt wzorca, którego można używać wielokrotnie.re.match()– próbuje dopasować wzorzec na początku łańcucha. Wzorzec jest zakotwiczony na pozycji 0.re.search()– próbuje dopasować wzorzec w dowolnym miejscu łańcucha. Zwraca pierwsze dopasowanie.re.sub()– znajduje każde dopasowanie i je zastępuje.
Istotne braki w porównaniu z CPython: brak re.findall, brak re.finditer, brak re.split na poziomie modułu (skompilowane wzorce mają zamiast tego metodę split), brak re.fullmatch, brak stałych flag, takich jak re.IGNORECASE. Tam, gdzie w CPython sięgnąłbyś po jedną z nich, zbuduj odpowiednik z re.search() w pętli.
2.35.2. Pierwszy wzorzec¶
Wzorzec r'\d+' dopasowuje jedną lub więcej cyfr:
>>> import re
>>> m = re.search(r'\d+', 'sensor reading 42 ok')
>>> m.group(0)
'42'
Kilka rzeczy, na które warto zwrócić uwagę:
Wzorzec zapisano jako surowy łańcuch (
r'...'), aby ukośnik wsteczny w\dtrafił dore, zamiast być przetwarzanym jako sekwencja ucieczki łańcucha Python. Zawsze używaj surowych łańcuchów dla wzorców wyrażeń regularnych.re.search()w razie powodzenia zwraca obiekt dopasowania, a w razie niepowodzeniaNone. Zawsze sprawdzaj wynik przed wywołaniemmatch.group().m.group(0)to pełny tekst dopasowany przez wzorzec. Grupa 1, 2, … pojawiają się później, gdy wzorzec zawiera nawiasy przechwytujące.
Ten sam wzorzec z re.match() zwraca None, ponieważ łańcuch nie zaczyna się od cyfry:
>>> re.match(r'\d+', 'sensor reading 42 ok') is None
True
>>> re.match(r'\d+', '42 readings')
<match num=1>
2.35.3. Elementy wzorca¶
Większość użytecznych wzorców jest zbudowana z niewielkiego zbioru elementów. Te, które działają w MicroPython:
Znaki literalne – każdy znak, który nie jest specjalny, dopasowuje sam siebie. hello dopasowuje hello.
Znaki specjalne – . ^ $ * + ? { } [ ] \ | ( ) mają znaczenia opisane poniżej. Aby dopasować jeden z nich literalnie, poprzedź go ukośnikiem wstecznym: \. dopasowuje literalną kropkę.
Klasy znaków – skróty dla typowych zbiorów znaków:
\d– dowolna cyfra0-9\D– dowolny znak niebędący cyfrą\s– dowolny znak białej spacji (spacja, tabulator, znak nowej linii)\S– dowolny znak niebędący białą spacją\w– dowolny znak „wyrazowy”: litery, cyfry, podkreślenie\W– dowolny znak niewyrazowy.– dowolny znak z wyjątkiem znaku nowej linii
Kwantyfikatory – ile razy poprzedni element musi się dopasować:
*– zero lub więcej (zachłanny)+– jedno lub więcej (zachłanny)?– zero lub jeden{n}– dokładnie n{m,n}– pomiędzy m a n (włącznie)
Łączenie: \d{3}-\d{4} dopasowuje trzy cyfry, myślnik, cztery cyfry. \s+ dopasowuje jeden lub więcej znaków białej spacji. hello.*world dopasowuje hello, cokolwiek (w tym nic), a następnie world.
Informacja
Zachłanny oznacza, że kwantyfikator pochłania tyle wejścia, ile zdoła, wciąż pozwalając reszcie wzorca się dopasować. W tekście hello x world y world .* we wzorcu hello.*world dopasowuje najdłuższy ciąg, który nadal pozostawia world na końcu – przechwytuje x world y, a nie krótsze x. To samo dotyczy + oraz formy zakresowej {m,n}: silnik bierze najdłuższe możliwe dopasowanie, a cofa się tylko wtedy, gdy reszta wzorca zawiedzie.
2.35.4. Podstawianie¶
re.sub() znajduje każde dopasowanie i zastępuje je łańcuchem. Zastąpienie może odwoływać się do przechwyconych grup za pomocą \1, \2, … (omówione później wraz z resztą składni grup). Bez grup re.sub jest zwykłym znajdź-i-zastąp na wyrażeniu regularnym:
>>> re.sub(r'\s+', ' ', 'too many spaces')
'too many spaces'
>>> re.sub(r'\d+', 'N', 'log 12, log 345, log 6')
'log N, log N, log N'
Trzeci argument to łańcuch, na którym ma działać operacja; wynikiem jest nowy łańcuch z zastąpionym każdym dopasowaniem.
2.35.5. Dzielenie – tylko na skompilowanym wzorcu¶
Nie ma re.split na poziomie modułu. Aby podzielić według wyrażenia regularnego, najpierw skompiluj wzorzec i wywołaj jego metodę split
>>> sep = re.compile(r'\s*,\s*')
>>> sep.split('a , b,c , d')
['a', 'b', 'c', 'd']
Opcjonalny drugi argument ogranicza liczbę podziałów:
>>> sep.split('a, b, c, d', 2)
['a', 'b', 'c, d']
2.35.6. Kompilowanie do wielokrotnego użycia¶
Jeśli ten sam wzorzec jest uruchamiany wiele razy – wewnątrz pętli lub w gorącej funkcji – skompiluj go raz i używaj skompilowanego obiektu wielokrotnie:
digit_run = re.compile(r'\d+')
def first_number(line):
m = digit_run.search(line)
return int(m.group(0)) if m else None
Wywołanie pattern.match() i pattern.search() na skompilowanym obiekcie działa tak samo jak funkcje na poziomie modułu, ale pomija koszt rekompilacji przy każdym wywołaniu.
2.35.7. Wzorce, które niczego nie dopasowują¶
Trzy wzorce w szczególności zaskakują programistów:
.*dopasowuje pusty łańcuch.re.search(r'.*', s).group(0)zwraca''dla dowolnego wejścia.Wzorzec z niepoprzedzonym ucieczką znakiem specjalnym jest błędem składni.
re.compile(r'cost: $5')zgłaszaValueError, ponieważ$oznacza „koniec łańcucha”. Użyjr'cost: \$5'.Kropka
.nie dopasowuje znaku nowej linii. Aby dopasowywać przez znaki nowej linii, napisz wzorzec obsługujący je jawnie za pomocą[\s\S]lub podawaj po jednym wierszu naraz.
Dzięki tym elementom wzorzec może dopasować niemal dowolny fragment tekstu o ustalonej formie. Wyciągnięcie z dopasowania strukturalnych danych wymaga grup przechwytujących.