Sök…


Introduktion

Python gör regelbundna uttryck tillgängliga via re modulen.

Vanliga uttryck är kombinationer av tecken som tolkas som regler för att matcha underlag. Exempelvis kommer uttrycket 'amount\D+\d+' att matcha vilken sträng som helst som består av amount plus ett integrerat antal, separerat med en eller flera icke-siffror, såsom: amount=100 , amount is 3 , amount is equal to: 33 , etc.

Syntax

  • Direkt reguljära uttryck

  • re.match (mönster, sträng, flagga = 0) # Ut: matcha mönstret i början av strängen eller Ingen

  • re.search (mönster, sträng, flagga = 0) # Ut: matcha mönstret inuti strängen eller Inget

  • re.findall (mönster, sträng, flagga = 0) # Ut: lista över alla matchningar av mönster i sträng eller []

  • re.finditer (mönster, sträng, flagga = 0) # Out: samma som re.findall, men returnerar iteratorobjekt

  • re.sub (mönster, ersättning, sträng, flagga = 0) # Ut: sträng med ersättning (sträng eller funktion) i stället för mönster

  • Förkompilerade regelbundna uttryck

  • precompiled_pattern = re.compile (mönster, flagga = 0)

  • precompiled_pattern.match (string) # Out: matcha i början av strängen eller Ingen

  • precompiled_pattern.search (string) # Out: matcha var som helst i strängen eller Ingen

  • precompiled_pattern.findall (string) # Out: lista över alla matchande underlag

  • precompiled_pattern.sub (sträng / mönster / funktion, sträng) # Out: ersatt sträng

Matchar början av en sträng

Det första argumentet om re.match() är det reguljära uttrycket, det andra är strängen som ska matchas:

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'

Du kanske märker att mönstervariabeln är en sträng förinställd med r , vilket indikerar att strängen är en rå sträng bokstavlig .

En rå strängbokstav har en något annorlunda syntax än en strängbokstavlig, nämligen ett motstreck \ i en rå strängbokstavlig betyder "bara ett motstreck" och det finns inget behov av att fördubbla upp bakslag för att undkomma "flygsekvenser" som nylinjer ( \n ) , flikar ( \t ), bakutrymmen ( \ ), form-feeds ( \r ) och så vidare. I normala strängbokstäver måste varje motsträcka fördubblas för att undvika att tas som början på en flyktningssekvens.

Följaktligen är r"\n" en sträng med två tecken: \ och n . Regex-mönster använder också motstreck, t.ex. \d hänvisar till alla siffror. Vi kan undvika att behöva dubbel undkomma våra strängar ( "\\d" ) genom att använda råa strängar ( r"\d" ).

Till exempel:

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'

Matchningen sker endast från början av strängen. Om du vill matcha var som helst använder du re.search istället:

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

match is None
# Out: True

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

match.group()
# Out: '123'

Sökande

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.'

Sökning görs var som helst i strängen till skillnad från re.match . Du kan också använda re.findall .

Du kan också söka i början av strängen (använd ^ ),

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

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

i slutet av strängen (använd $ ),

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

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

eller båda (använd både ^ och $ ):

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

gruppera

Gruppering sker med parenteser. Ringgrupp group() returnerar en sträng som bildas av de matchande parentesbaserade undergrupperna.

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'

Argument kan också tillhandahållas för group() att hämta en viss undergrupp.

Från dokumenten :

Om det finns ett enda argument är resultatet en enda sträng; om det finns flera argument är resultatet en tupel med ett objekt per argument.

Återuppringningsgrupper groups() å andra sidan returnerar en lista med tupler som innehåller undergrupperna.

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')

Namngivna grupper

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'

Skapar en fångstgrupp som kan refereras till med namn och index.

Icke-fånga grupper

Att använda (?:) skapar en grupp, men gruppen fångas inte. Detta betyder att du kan använda den som en grupp, men det förorenar inte ditt "grupputrymme".

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

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

Detta exempel matchar 11+22 eller 11 , men inte 11+ . Det är eftersom + -tecknet och den andra termen är grupperade. Å andra sidan är + -tecknet inte fångat.

Rymmer specialtecken

Specialtecken (som teckenklassen inom parentes [ och ] nedan) matchas inte bokstavligen:

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

Genom att undkomma specialtecken kan de matchas bokstavligen:

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

re.escape() kan användas för att göra detta åt dig:

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'

re.escape() undgår alla specialtecken, så det är användbart om du skriver ett vanligt uttryck baserat på användarinmatning:

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.!']

Byter ut

Ersättningar kan göras på strängar med re.sub .

Byt ut strängar

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'

Med hjälp av gruppreferenser

Ersättningar med ett litet antal grupper kan göras enligt följande:

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

Men om du skapar ett grupp-ID som '10' fungerar det inte : \10 läses som 'ID nummer 1 följt av 0'. Så du måste vara mer specifik och använda \g<i> notationen:

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

Med en ersättningsfunktion

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'

Hitta alla matchningar som inte överlappar varandra

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

Observera att r före "[0-9]{2,3}" säger python att tolka strängen som den är; som en "rå" sträng.

Du kan också använda re.finditer() som fungerar på samma sätt som re.findall() men returnerar en iterator med SRE_Match objekt i stället för en lista med strängar:

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
'''

Förkompilerade mönster

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

Genom att sammanställa ett mönster kan det återanvändas senare i ett program. Observera dock att Python cachar nyligen använda uttryck ( dokument , SO-svar ), så "program som bara använder några få reguljära uttryck i taget behöver inte oroa sig för att sammanställa regelbundna uttryck" .

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

Det kan användas med re.match ().

Kontrollerar för tillåtna tecken

Om du vill kontrollera att en sträng endast innehåller en viss uppsättning tecken, i detta fall az, AZ och 0-9, kan du göra det så här,

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'

Du kan också anpassa uttryckslinjen från [^a-zA-Z0-9.] Till [^a-z0-9.] , För att till exempel tillåta stora bokstäver.

Delkredit: http://stackoverflow.com/a/1325265/2697955

Dela upp en sträng med vanliga uttryck

Du kan också använda vanliga uttryck för att dela en sträng. Till exempel,

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

flaggor

För vissa speciella fall måste vi ändra beteendet hos Regular Expression, detta görs med flaggor. Flaggor kan ställas in på två sätt, genom nyckelordet för flags eller direkt i uttrycket.

Flaggor nyckelord

Nedanför ett exempel för re.search men det fungerar för de flesta funktioner i re modulen.

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'

Vanliga flaggor

Flagga kort beskrivning
re.IGNORECASE , re.I Gör mönstret att ignorera fallet
re.DOTALL , re.S Gör . matcha allt inklusive nyheter
re.MULTILINE , re.M Gör ^ matcha början på en linje och $ slutet av en rad
re.DEBUG Aktiverar felsökningsinformation

Kontrollera dokumenten för den kompletta listan över alla tillgängliga flaggor

Inline flaggor

Från dokumenten :

(?iLmsux) (En eller flera bokstäver från uppsättningen 'i', 'L', 'm', 's', 'u', 'x'.)

Gruppen matchar den tomma strängen; bokstäverna ställer in motsvarande flaggor: re.I (ignorera fall), re.L (språkberoende), re.M (multilinje), re.S (punkt matchar alla), re.U (Unicode-beroende) och re.X (ordbok), för hela det reguljära uttrycket. Detta är användbart om du vill inkludera flaggorna som en del av det reguljära uttrycket, istället för att överföra ett flaggargument till funktionen re.compile ().

Observera att (? X) -flaggan ändrar hur uttrycket analyseras. Det bör användas först i uttryckssträngen, eller efter ett eller flera blankstegstecken. Om det finns tecken som inte är whitespace före flaggan, definieras resultaten.

Iterera över matcher med `re.finditer`

Du kan använda re.finditer att iterera över alla matchningar i en sträng. Detta ger dig (jämfört med re.findall extra information, till exempel information om matchplatsen i strängen (index):

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))

Resultat:

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

Matcha ett uttryck endast på specifika platser

Ofta vill du matcha ett uttryck endast på specifika platser (lämna dem orörda i andra, det vill säga). Tänk på följande mening:

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

Här förekommer "äpplet" två gånger som kan lösas med så kallade backtracking-kontrollverb som stöds av den nyare regex modulen. Idén är:

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

Med vårt äppleexempel skulle detta vara:

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

Detta matchar "äpple" endast när det finns utanför parenteserna.


Så här fungerar det:
  • Medan man tittar från vänster till höger , konsumerar regex-motorn allt till vänster, (*SKIP) fungerar som en "alltid-sann-påstående". Efteråt misslyckas det korrekt på (*FAIL) och backspår.
  • Nu kommer det till punkten (*SKIP) från höger till vänster (även under backtracking) där det är förbjudet att gå längre åt vänster. Istället får motoren besked om att kasta bort allt åt vänster och hoppa till den punkt där (*SKIP) åberopades.


Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow