Zanurkuj w Pythonie/Składnia ?n, m?

Z Wikibooks, biblioteki wolnych podręczników.

Składnia {n, m}[edytuj]

W poprzednim podrozdziale poznaliśmy wzorce, w których ten sam znak mógł się powtarzać co najwyżej trzy razy. Tutaj przedstawimy inny sposób zapisania takiego wyrażenia, a który wydaje się być bardziej czytelny. Najpierw spójrzmy na metody wykorzystane w poprzednim przykładzie.

Przykład. Stary sposób: każdy znak opcjonalny
>>> import re
>>> pattern = '^M?M?M?$'
>>> re.search(pattern, 'M')   #(1)
<_sre.SRE_Match object at 0x008EE090>
>>> pattern = '^M?M?M?$'
>>> re.search(pattern, 'MM')   #(2)
<_sre.SRE_Match object at 0x008EEB48>
>>> pattern = '^M?M?M?$'
>>> re.search(pattern, 'MMM')  #(3)
<_sre.SRE_Match object at 0x008EE090>
>>> re.search(pattern, 'MMMM') #(4)
  1. Instrukcja ta dopasowuje początek napisu, a następnie pierwszą literę M, lecz nie dopasowuje drugiego i trzeciego M (wszystko jest w porządku, ponieważ są one opcjonalne), a następnie koniec napisu.
  2. Tutaj zostaje dopasowany początek napisu, a następnie pierwsze i drugie opcjonalne M, jednak nie zostaje dopasowane trzecie M (ale wszystko jest w ok, ponieważ jest to opcjonalne), ale zostaje dopasowany koniec napisu.
  3. Zostanie dopasowany początek napisu, a następnie wszystkie opcjonalne M, a potem koniec napisu.
  4. Dopasowany zostanie początek napisu, następnie wszystkie opcjonalne M, jednak koniec tekstu nie zostanie dopasowany, ponieważ pozostanie jedno niedopasowane M, dlatego też nic nie zostanie dopasowane, a operacja zwróci None.
Przykład. Nowy sposób: od n do m
>>> pattern = '^M{0,3}$'       #(1)
>>> re.search(pattern, 'M')    #(2)
<_sre.SRE_Match object at 0x008EEB48>
>>> re.search(pattern, 'MM')   #(3)
<_sre.SRE_Match object at 0x008EE090>
>>> re.search(pattern, 'MMM')  #(4)
<_sre.SRE_Match object at 0x008EEDA8>
>>> re.search(pattern, 'MMMM') #(5)
  1. Ten wzorzec mówi: "dopasuj początek napisu, potem od zera do trzech znaków M, a następnie koniec napisu". 0 i 3 może być dowolną liczbą. Jeśli chcielibyśmy dopasować co najmniej jeden, lecz nie więcej niż trzy znaki M, powinienniśmy napisać M{1,3}.
  2. Dopasowujemy początek napisu, potem jeden znak M z trzech możliwych, a następnie koniec napisu.
  3. Tutaj zostaje dopasowany początek napisu, następnie dwa M z trzech możliwych, a następnie koniec napisu.
  4. Zostanie dopasowany początek napisu, potem trzy znaki M z trzech możliwych, a następnie koniec napisu.
  5. W tym miejscu dopasowujemy początek napisu, potem trzy znaki M z pośród trzech możliwych, lecz nie dopasujemy końca napisu. To wyrażenie regularne pozwala wykorzystać tylko trzy litery M, zanim dojdzie do końca napisu, a my mamy cztery, więc ten wzorzec niczego nie dopasuje i zwróci None.

Sprawdzanie dziesiątek i jedności[edytuj]

Teraz rozszerzmy wyrażenie wykrywające liczby rzymskie, żeby odnajdywało też dziesiątki i jedności. Ten przykład pokazuje sprawdzanie dziesiątek.

Przykład. Sprawdzanie dziesiątek
>>> pattern = '^M?M?M?(CM|CD|D?C?C?C?)(XC|XL|L?X?X?X?)$'
>>> re.search(pattern, 'MCMXL')    #(1)
<_sre.SRE_Match object at 0x008EEB48>
>>> re.search(pattern, 'MCML')     #(2)
<_sre.SRE_Match object at 0x008EEB48>
>>> re.search(pattern, 'MCMLX')    #(3)
<_sre.SRE_Match object at 0x008EEB48>
>>> re.search(pattern, 'MCMLXXX')  #(4)
<_sre.SRE_Match object at 0x008EEB48>
>>> re.search(pattern, 'MCMLXXXX') #(5)
  1. To dopasuje początek łańcucha, potem pierwsze opcjonalne M, dalej CM i XL, a potem koniec łańcucha. Zapamiętajmy, że składnia (A|B|C) oznacza "dopasuj dokładnie jedno z A, B lub C". W tym wypadku dopasowaliśmy XL, więc ignorujemy XC i L?X?X?X? i przechodzimy do końca łańcucha. MCMXL to 1940.
  2. Tutaj dopasowujemy początek łańcucha, pierwsze opcjonalne M, potem CM i L?X?X?X?. Z tego ostatniego elementu dopasowane zostaje tylko L, a opcjonalne X zostają pominięte. Potem przechodzimy na koniec łańcucha. MCML to 1950.
  3. Dopasowuje początek napisu, potem pierwsze opcjonalne M, następnie CM, potem opcjonalne L i pierwsze opcjonalne X, pomijając drugie i trzecie opcjonalne X, a następnie dopasowuje koniec napisu. MCMLX jest rzymską reprezentacją liczby 1960.
  4. Tutaj zostanie dopasowany początek napisu, następnie pierwsze opcjonalne M, potem CM, następnie opcjonalne L, wszystkie trzy opcjonalne znaki X i w końcu dopasowany zostanie koniec napisu. MCMLXXX jest rzymską reprezentacją liczby 1980.
  5. To dopasuje początek napisu, następnie pierwsze opcjonalne M, potem CM, opcjonalne L, wszystkie trzy opcjonalne znaki X, jednak nie może dopasować końca napisu, ponieważ pozostał jeszcze jeden niewliczony znak X. Zatem cały wzorzec nie zostanie dopasowany, więc zostanie zwrócone None. MCMLXXXX nie jest poprawną liczbą rzymską.

Poniżej przedstawiono podobne wyrażenie, które dodatkowo sprawdza jedności. Oszczędzimy sobie szczegółów.

>>> pattern = '^M?M?M?(CM|CD|D?C?C?C?)(XC|XL|L?X?X?X?)(IX|IV|V?I?I?I?)$'

Jak będzie wyglądało to wyrażenie wykorzystując składnię {n,m}? Zobaczmy na poniższy przykład.

Przykład. Sprawdzanie liczb rzymskich korzystając ze składni {n, m}
>>> pattern = '^M{0,3}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$'
>>> re.search(pattern, 'MDLV')             #(1)
<_sre.SRE_Match object at 0x008EEB48>
>>> re.search(pattern, 'MMDCLXVI')         #(2)
<_sre.SRE_Match object at 0x008EEB48>
>>> re.search(pattern, 'MMMDCCCLXXXVIII') #(3)
<_sre.SRE_Match object at 0x008EEB48>
>>> re.search(pattern, 'I')                #(4)
<_sre.SRE_Match object at 0x008EEB48>
  1. Dopasowany zostanie początek napisu, potem jeden z możliwych czterech znaków M i następnie D?C{0,3}. Z kolei D?C{0,3} dopasuje opcjonalny znak D i zero z trzech możliwych znaków C. Idąc dalej, dopasowany zostanie L?X{0,3} poprzez dopasowanie opcjonalnego znaku L i zero z możliwych trzech znaków X. Następnie dopasowujemy V?I{0,3} dodając opcjonalne V i zero z trzech możliwych znaków I, a ostatecznie dopasowujemy koniec napisu. MDLV jest rzymską reprezentacją liczby 1555.
  2. To dopasuje początek napisu, następnie dwa z czterech możliwych znaków M, a potem D?C{0,3} z D i jednym z trzech możliwych znaków C. Dalej dopasujemy L?X{0,3} z L i jednym z trzech możliwych znaków X, a następnie V?I{0,3} z V i jednym z trzech możliwych znaków I, a w końcu koniec napisu. MMDCLXVI jest reprezentacją liczby 2666.
  3. Tutaj dopasowany zostanie początek napisu, a potem trzy z trzech znaków M, a następnie D?C{0,3} ze znakiem D i trzema z trzech możliwych znaków C. Potem dopasujemy L?X{0,3} z L i trzema z trzech znaków X, następnie V?I{0,3} z V i trzema z trzech możliwych znaków I, a ostatecznie koniec napisu. MMMDCCCLXXXVIII jest reprezentacją liczby 3888 i ponadto jest najdłuższą liczbą Rzymską, którą można zapisać bez rozszerzonej składni.
  4. Obserwuj dokładnie. Dopasujemy początek napisu, potem zero z czterech M, następnie dopasowujemy D?C{0,3} pomijając opcjonalne D i dopasowując zero z trzech znaków C. Następnie dopasowujemy L?X{0,3} pomijając opcjonalne L i dopasowując zero z trzech znaków X, a potem dopasowujemy V?I{0,3} pomijając opcjonalne V, ale dopasowując jeden z trzech możliwych I. Ostatecznie dopasowujemy koniec napisu.

Jeśli prześledziłeś to wszystko i zrozumiałeś to za pierwszym razem, jesteś bardzo bystry. Teraz wyobraźmy sobie sytuację, że próbujemy zrozumieć jakieś inne wyrażenie regularne, które znajduje się w centralnej, krytycznej funkcji wielkiego programu. Albo wyobraź sobie nawet, że wracasz do swojego wyrażenia regularnego po kilku miesiącach. Sytuacje takie mogą nie wyglądać ciekawie...

W następnym podrozdziale dowiemy się o alternatywnej składni, która pomaga zrozumieć i zarządzać wyrażeniami.