Zoeken…


Invoering

Python maakt reguliere expressies beschikbaar via de re module.

Reguliere expressies zijn combinaties van tekens die worden geïnterpreteerd als regels voor overeenkomende substrings. De uitdrukking 'amount\D+\d+' komt bijvoorbeeld overeen met elke tekenreeks die bestaat uit het woord amount plus een integraal nummer, gescheiden door een of meer niet-cijfers, zoals: amount=100 , amount is 3 , amount is equal to: 33 , enz.

Syntaxis

  • Directe reguliere expressies

  • re.match (patroon, string, vlag = 0) # Out: match patroon aan het begin van de string of Geen

  • re.search (patroon, string, vlag = 0) # Out: match patroon binnen string of Geen

  • re.findall (patroon, string, vlag = 0) # Out: lijst van alle overeenkomsten van patroon in string of []

  • re.finditer (patroon, string, vlag = 0) # Out: hetzelfde als re.findall, maar retourneert iteratorobject

  • re.sub (patroon, vervanging, string, vlag = 0) # Out: string met vervanging (string of functie) in plaats van patroon

  • Voorgecompileerde reguliere expressies

  • precompiled_pattern = re.compile (patroon, vlag = 0)

  • precompiled_pattern.match (string) # Out: match aan het begin van de string of Geen

  • precompiled_pattern.search (string) # Out: match overal in string of Geen

  • precompiled_pattern.findall (string) # Out: lijst van alle overeenkomende substrings

  • precompiled_pattern.sub (string / patroon / functie, string) # Out: vervangen string

Komt overeen met het begin van een string

Het eerste argument van re.match() is de reguliere expressie, het tweede is de overeenkomende tekenreeks:

import re

pattern = r"123"
string = "123zzb"

re.match(pattern, string)
# Out: <_sre.SRE_Match object; span=(0, 3), match='123'>

match = re.match(pattern, string)

match.group()
# Out: '123'

Het is je misschien opgevallen dat de patroonvariabele een tekenreeks is die wordt voorafgegaan door r , wat aangeeft dat de tekenreeks een onbewerkte tekenreeks is .

Een onbewerkte stringliter heeft een iets andere syntaxis dan een letterlijke string, namelijk een backslash \ in een onbewerkte stringliter betekent "slechts een backslash" en het is niet nodig om backlashes te verdubbelen om te ontsnappen aan "escape sequenties" zoals newlines ( \n ) , tabs ( \t ), backspaces ( \ ), form-feeds ( \r ), enzovoort. In normale stringliterals moet elke backslash worden verdubbeld om te voorkomen dat deze wordt genomen als het begin van een escape-reeks.

Daarom is r"\n" een reeks van 2 tekens: \ en n . Regex-patronen gebruiken ook backslashes, bijv. \d verwijst naar elk willekeurig cijfer. We kunnen voorkomen dat we dubbel moeten ontsnappen aan onze strings ( "\\d" ) door onbewerkte strings ( r"\d" ) te gebruiken.

Bijvoorbeeld:

string = "\\t123zzb" # here the backslash is escaped, so there's no tab, just '\' and 't'
pattern = "\\t123"   # this will match \t (escaping the backslash) followed by 123
re.match(pattern, string).group()   # no match
re.match(pattern, "\t123zzb").group()  # matches '\t123'

pattern = r"\\t123"  
re.match(pattern, string).group()   # matches '\\t123'

Het matchen vindt alleen vanaf het begin van de string plaats. Als je overal wilt matchen, gebruik dan re.search :

match = re.match(r"(123)", "a123zzb")

match is None
# Out: True

match = re.search(r"(123)", "a123zzb")

match.group()
# Out: '123'

Zoeken

pattern = r"(your base)"
sentence = "All your base are belong to us."

match = re.search(pattern, sentence)
match.group(1)
# Out: 'your base'

match = re.search(r"(belong.*)", sentence)
match.group(1)
# Out: 'belong to us.'

Zoeken vindt overal in de string plaats, in tegenstelling tot re.match . Je kunt ook re.findall .

Je kunt ook zoeken aan het begin van de string (gebruik ^ ),

match = re.search(r"^123", "123zzb")
match.group(0)
# Out: '123'

match = re.search(r"^123", "a123zzb")
match is None
# Out: True

aan het einde van de string (gebruik $ ),

match = re.search(r"123$", "zzb123")
match.group(0)
# Out: '123'

match = re.search(r"123$", "123zzb")
match is None
# Out: True

of beide (gebruik zowel ^ als $ ):

match = re.search(r"^123$", "123")
match.group(0)
# Out: '123'

Groepering

Groeperen gebeurt tussen haakjes. Calling group() retourneert een tekenreeks gevormd uit de overeenkomende haakjes subgroepen.

match.group() # Group without argument returns the entire match found
# Out: '123'
match.group(0) # Specifying 0 gives the same result as specifying no argument
# Out: '123'

Er kunnen ook argumenten worden gegeven aan group() om een bepaalde subgroep op te halen.

Uit de documenten :

Als er een enkel argument is, is het resultaat een enkele string; als er meerdere argumenten zijn, is het resultaat een tuple met één item per argument.

Aanroepen van groups() daarentegen, retourneert een lijst met tupels die de subgroepen bevatten.

sentence = "This is a phone number 672-123-456-9910"
pattern = r".*(phone).*?([\d-]+)"

match = re.match(pattern, sentence)

match.groups()   # The entire match as a list of tuples of the paranthesized subgroups
# Out: ('phone', '672-123-456-9910')

m.group()        # The entire match as a string
# Out: 'This is a phone number 672-123-456-9910'

m.group(0)       # The entire match as a string
# Out: 'This is a phone number 672-123-456-9910'

m.group(1)       # The first parenthesized subgroup.
# Out: 'phone'

m.group(2)       # The second parenthesized subgroup.
# Out: '672-123-456-9910'

m.group(1, 2)    # Multiple arguments give us a tuple.
# Out: ('phone', '672-123-456-9910')

Benoemde groepen

match = re.search(r'My name is (?P<name>[A-Za-z ]+)', 'My name is John Smith')
match.group('name')
# Out: 'John Smith'

match.group(1)
# Out: 'John Smith'

Hiermee maakt u een opnamegroep waarnaar zowel op naam als op index kan worden verwezen.

Niet-vastleggende groepen

Met (?:) een groep gemaakt, maar de groep wordt niet vastgelegd. Dit betekent dat u het als een groep kunt gebruiken, maar het zal uw "groepsruimte" niet vervuilen.

re.match(r'(\d+)(\+(\d+))?', '11+22').groups()
# Out: ('11', '+22', '22')

re.match(r'(\d+)(?:\+(\d+))?', '11+22').groups()
# Out: ('11', '22')

Dit voorbeeld komt overeen met 11+22 of 11 , maar niet 11+ . Dit komt omdat het + -teken en de tweede term gegroepeerd zijn. Aan de andere kant wordt het + -teken niet vastgelegd.

Ontsnappen aan speciale tekens

Speciale tekens (zoals de karakterklasse haakjes [ en ] hieronder) komen niet letterlijk overeen:

match = re.search(r'[b]', 'a[b]c')
match.group()
# Out: 'b'

Door aan de speciale karakters te ontsnappen, kunnen ze letterlijk worden gematcht:

match = re.search(r'\[b\]', 'a[b]c')
match.group()
# Out: '[b]'

De functie re.escape() kan hiervoor worden gebruikt:

re.escape('a[b]c')
# Out: 'a\\[b\\]c'
match = re.search(re.escape('a[b]c'), 'a[b]c')
match.group()
# Out: 'a[b]c'

De functie re.escape() ontsnapt aan alle speciale tekens, dus het is handig als u een reguliere expressie samenstelt op basis van gebruikersinvoer:

username = 'A.C.'  # suppose this came from the user
re.findall(r'Hi {}!'.format(username), 'Hi A.C.! Hi ABCD!')
# Out: ['Hi A.C.!', 'Hi ABCD!']
re.findall(r'Hi {}!'.format(re.escape(username)), 'Hi A.C.! Hi ABCD!')
# Out: ['Hi A.C.!']

Vervangen

Vervangingen kunnen op reeksen worden gemaakt met re.sub .

Tekenreeksen vervangen

re.sub(r"t[0-9][0-9]", "foo", "my name t13 is t44 what t99 ever t44")
# Out: 'my name foo is foo what foo ever foo'

Groepsreferenties gebruiken

Vervangingen door een klein aantal groepen kunnen als volgt worden gemaakt:

re.sub(r"t([0-9])([0-9])", r"t\2\1", "t13 t19 t81 t25")
# Out: 't31 t91 t18 t52'

Als u echter een groeps-ID zoals '10' maakt, werkt dit niet : \10 wordt gelezen als 'ID nummer 1 gevolgd door 0'. Je moet dus specifieker zijn en de \g<i> -notatie gebruiken:

re.sub(r"t([0-9])([0-9])", r"t\g<2>\g<1>", "t13 t19 t81 t25")
# Out: 't31 t91 t18 t52'

Een vervangende functie gebruiken

items = ["zero", "one", "two"]
re.sub(r"a\[([0-3])\]", lambda match: items[int(match.group(1))], "Items: a[0], a[1], something, a[2]")
# Out: 'Items: zero, one, something, two'

Vind alle niet-overlappende overeenkomsten

re.findall(r"[0-9]{2,3}", "some 1 text 12 is 945 here 4445588899")
# Out: ['12', '945', '444', '558', '889']

Merk op dat de r vóór "[0-9]{2,3}" python vertelt om de string als zodanig te interpreteren; als een "ruwe" string.

Je kunt ook re.finditer() die op dezelfde manier werkt als re.findall() maar een iterator retourneert met SRE_Match objecten in plaats van een lijst met tekenreeksen:

results = re.finditer(r"([0-9]{2,3})", "some 1 text 12 is 945 here 4445588899")
print(results)
# Out: <callable-iterator object at 0x105245890>
for result in results:
     print(result.group(0))
''' Out:
12
945
444
558
889
'''

Voorgecompileerde patronen

import re

precompiled_pattern = re.compile(r"(\d+)")
matches = precompiled_pattern.search("The answer is 41!")
matches.group(1)
# Out: 41

matches = precompiled_pattern.search("Or was it 42?")
matches.group(1)
# Out: 42

Door een patroon samen te stellen, kan het later opnieuw worden gebruikt in een programma. Merk echter op dat Python recent gebruikte expressies in de cache opslaat ( docs , SO answer ), dus "programma's die slechts een paar reguliere expressies tegelijkertijd gebruiken, hoeven zich geen zorgen te maken over het compileren van reguliere expressies" .

import re

precompiled_pattern = re.compile(r"(.*\d+)")
matches = precompiled_pattern.match("The answer is 41!")
print(matches.group(1))
# Out: The answer is 41

matches = precompiled_pattern.match("Or was it 42?")
print(matches.group(1))
# Out: Or was it 42

Het kan worden gebruikt met re.match ().

Controleren op toegestane tekens

Als je wilt controleren of een string alleen een bepaalde set tekens bevat, in dit geval az, AZ en 0-9, kun je dit als volgt doen,

import re

def is_allowed(string):
    characherRegex = re.compile(r'[^a-zA-Z0-9.]')
    string = characherRegex.search(string)
    return not bool(string)
    
print (is_allowed("abyzABYZ0099")) 
# Out: 'True'

print (is_allowed("#*@#$%^")) 
# Out: 'False'

U kunt ook de expressieregel aanpassen van [^a-zA-Z0-9.] [^a-z0-9.] , Om bijvoorbeeld hoofdletters niet toe te staan.

Gedeeltelijk tegoed: http://stackoverflow.com/a/1325265/2697955

Een tekenreeks splitsen met reguliere expressies

U kunt ook reguliere expressies gebruiken om een string te splitsen. Bijvoorbeeld,

import re
data = re.split(r'\s+', 'James 94 Samantha 417 Scarlett 74')
print( data )
# Output: ['James', '94', 'Samantha', '417', 'Scarlett', '74']

vlaggen

Voor sommige speciale gevallen moeten we het gedrag van de reguliere expressie wijzigen, dit gebeurt met vlaggen. Vlaggen kan worden ingesteld op twee manieren, door middel van de flags trefwoord of rechtstreeks in de expressie.

Vlaggen trefwoord

Hieronder een voorbeeld voor re.search maar het werkt voor de meeste functies in de re module.

m = re.search("b", "ABC")  
m is None
# Out: True

m = re.search("b", "ABC", flags=re.IGNORECASE)
m.group()
# Out: 'B'

m = re.search("a.b", "A\nBC", flags=re.IGNORECASE) 
m is None
# Out: True

m = re.search("a.b", "A\nBC", flags=re.IGNORECASE|re.DOTALL) 
m.group()
# Out: 'A\nB'

Gemeenschappelijke vlaggen

Vlag korte beschrijving
re.IGNORECASE , re.I Laat het patroon de zaak negeren
re.DOTALL , re.S Maakt . match alles inclusief nieuwe lijnen
re.MULTILINE , re.M Zorgt ervoor dat ^ overeenkomt met het begin van een regel en $ het einde van een regel
re.DEBUG Schakelt foutopsporingsinformatie in

Raadpleeg de documenten voor de volledige lijst van alle beschikbare vlaggen

Inline vlaggen

Uit de documenten :

(?iLmsux) (Een of meer letters van de set 'i', 'L', 'm', 's', 'u', 'x'.)

De groep komt overeen met de lege string; de letters stellen de overeenkomstige vlaggen in: re.I (hoofdletter negeren), re.L (locale afhankelijk), re.M (multi-line), re.S (punt komt overeen met alles), re.U (Unicode afhankelijk), en re.X (uitgebreid), voor de gehele reguliere expressie. Dit is handig als u de vlaggen wilt opnemen als onderdeel van de reguliere expressie, in plaats van een vlagargument door te geven aan de functie re.compile ().

Merk op dat de vlag (? X) verandert hoe de uitdrukking wordt geparseerd. Het moet eerst in de expressiereeks worden gebruikt, of na een of meer witruimte-tekens. Als er niet-witruimtetekens vóór de vlag staan, zijn de resultaten niet gedefinieerd.

Herhalen van wedstrijden met `re.finditer`

Je kunt re.finditer om alle overeenkomsten in een string te herhalen. Dit geeft u (in vergelijking met re.findall extra informatie, zoals informatie over de re.findall in de string (indexen):

import re
text = 'You can try to find an ant in this string'
pattern = 'an?\w' # find 'an' either with or without a following word character

for match in re.finditer(pattern, text):
    # Start index of match (integer)
    sStart = match.start()

    # Final index of match (integer)
    sEnd = match.end()

    # Complete match (string)
    sGroup = match.group()

    # Print match
    print('Match "{}" found at: [{},{}]'.format(sGroup, sStart,sEnd))

Resultaat:

Match "an" found at: [5,7]
Match "an" found at: [20,22]
Match "ant" found at: [23,26]

Pas een uitdrukking alleen op specifieke locaties aan

Vaak wilt u een uitdrukking alleen op specifieke plaatsen matchen (ze op andere plaatsen onaangeroerd laten). Overweeg de volgende zin:

An apple a day keeps the doctor away (I eat an apple everyday).

Hier komt de "appel" twee keer voor, die kan worden opgelost met zogenaamde backtracking-besturingswerkwoorden die worden ondersteund door de nieuwere regex module. Het idee is:

forget_this | or this | and this as well | (but keep this)

Met ons appelvoorbeeld zou dit zijn:

import regex as re
string = "An apple a day keeps the doctor away (I eat an apple everyday)."
rx = re.compile(r'''
    \([^()]*\) (*SKIP)(*FAIL)  # match anything in parentheses and "throw it away"
    |                          # or
    apple                      # match an apple
    ''', re.VERBOSE)
apples = rx.findall(string)
print(apples)
# only one

Dit komt alleen overeen met "appel" wanneer het buiten de haakjes staat.


Dit is hoe het werkt:
  • Kijkend van links naar rechts , verbruikt de regex-engine alles naar links, de (*SKIP) fungeert als een "altijd-ware-bewering". Nadien mislukt het correct op (*FAIL) en backtracks.
  • Nu komt het op het punt van (*SKIP) van rechts naar links (oftewel tijdens het achteruitrijden) waar het verboden is verder naar links te gaan. In plaats daarvan wordt de motor opgedragen iets naar links weg te gooien en naar het punt te springen waar de (*SKIP) is aangeroepen.


Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow