How to use alternation in regex?

Regex Alternation: Din Digitale Recept

11/06/2000

Rating: 4.11 (7327 votes)

I den digitale verden, ligesom i den menneskelige krop, kan små symptomer indikere behovet for en præcis behandling. Når du arbejder med tekstdata, er et almindeligt symptom behovet for at finde ét specifikt mønster ud af flere mulige. Uden det rette værktøj kan denne opgave føles som at lede efter en nål i en høstak. Heldigvis findes der en effektiv medicin i verdenen af regulære udtryk (regex): alternation. Denne kraftfulde teknik, repræsenteret ved det lodrette streg-symbol ( | ), fungerer som en 'enten/eller'-recept, der giver dig mulighed for at matche flere forskellige mønstre med kirurgisk præcision. I denne artikel vil vi dissekere alternationens anatomi, diagnosticere almindelige fejl og ordinere de bedste praksisser for at sikre, at din kode forbliver sund og robust.

How do I use alternation?
Alternation is similar. You can use alternation to match a single regular expression out of several possible regular expressions. If you want to search for the literal text cat or dog, separate both options with a vertical bar or pipe symbol: cat|dog. If you want more options, simply expand the list: cat|dog|mouse|fish.
Indholdsfortegnelse

Grundlæggende Diagnose: Hvad er Alternation?

Alternation er i sin kerne et af de mest intuitive, men alligevel kraftfulde, koncepter i regulære udtryk. Det lader dig specificere en liste af mulige udtryk, hvoraf kun ét behøver at matche for at hele mønsteret skal lykkes. Tænk på det som at give regex-motoren et valg.

Det primære symbol for alternation er den lodrette streg, |, ofte kaldet 'pipe'-symbolet. Hvis du vil søge efter enten det bogstavelige ord 'kat' eller 'hund', ville dit regex-mønster se således ud: kat|hund. Motoren vil læse dette som "match enten sekvensen 'k-a-t' ELLER sekvensen 'h-u-n-d'". Du kan udvide denne liste med så mange alternativer, du har brug for. For eksempel ville kat|hund|mus|fisk matche ethvert af disse fire dyr i en given tekst.

Denne funktion er fundamentalt forskellig fra tegnklasser (f.eks. [abc]), som kun tillader et valg mellem enkelte tegn. Alternation lader dig vælge mellem hele strenge eller endda komplekse undermønstre, hvilket giver en langt større fleksibilitet.

Symptomer på Forkert Brug: Præcedens og Gruppering

En af de mest almindelige faldgruber ved brug af alternation er at misforstå dens 'præcedens' i forhold til andre regex-operatorer. Alternationsoperatoren har den laveste præcedens af alle. Det betyder, at den forsøger at omfatte så meget som muligt til venstre og højre for sig selv. Dette kan føre til uventede og ukorrekte resultater, hvis det ikke håndteres korrekt.

Lad os forestille os, at vi vil matche ordene 'kat' eller 'hund', men kun som hele ord. En nybegynder kunne prøve mønsteret \bkat|hund\b. Her repræsenterer \b en ordgrænse. På grund af den lave præcedens fortolker regex-motoren dette som: "match en ordgrænse efterfulgt af 'kat'" ELLER "match 'hund' efterfulgt af en ordgrænse". Dette ville fejlagtigt matche 'kat' i 'katalog' og 'hund' i 'hunde', men ikke som isolerede ord.

How to represent an alternation in regular expressions?
To represent an alternation in regular expressions, you use the pipe operator ( | ). The pipe operator is called the alternation. It is like the or operator in Python. The following regular expression uses an alternation to match either the literal string complex and simple:

Behandlingen for dette symptom er gruppering ved hjælp af parenteser (). Parenteser fungerer som en afgrænsning, der begrænser alternationens rækkevidde. Det korrekte mønster ville være \b(kat|hund)\b. Her fortæller parenteserne motoren, at alternationen kun gælder for 'kat' og 'hund'. Hele mønsteret læses nu korrekt som: "find en ordgrænse, derefter enten 'kat' eller 'hund', og derefter endnu en ordgrænse". At bruge parenteser til at isolere din alternation er afgørende for at skrive præcise og forudsigelige regulære udtryk.

En Dybdegående Undersøgelse: Regex-motorens "Grådighed"

Ikke alle regex-motorer opfører sig ens, og dette er især tydeligt med alternation. De fleste moderne motorer (som dem i Python, JavaScript, .NET) er 'regex-styrede' og grådige. Det betyder, at motoren stopper sin søgning, så snart den finder et gyldigt match, selvom et længere, potentielt bedre match findes senere i strengen eller i alternationslisten.

Dette har en vigtig konsekvens: rækkefølgen af dine alternativer kan have betydning. Overvej et scenarie, hvor du vil matche funktionsnavne: Get, GetValue, Set eller SetValue. Et oplagt mønster ville være Get|GetValue|Set|SetValue. Hvis vi anvender dette på strengen "SetValue", sker følgende:

  1. Motoren prøver Get mod 'S'. Fejl.
  2. Motoren prøver næste alternativ, GetValue. Fejl.
  3. Motoren prøver Set. 'S' matcher, 'e' matcher, 't' matcher. Succes!

Fordi motoren er grådig, stopper den her. Den har fundet et match, 'Set', og rapporterer succes. Den forsøger ikke engang at matche SetValue, selvom det også ville have været et gyldigt og længere match. Resultatet er, at vi kun matcher en del af ordet, hvilket sandsynligvis ikke var intentionen.

Der er flere måder at behandle dette på:

  • Omarranger alternativerne: Placer de længste og mest specifikke alternativer først. Mønsteret GetValue|Get|SetValue|Set ville korrekt matche 'SetValue' først.
  • Gør dele valgfrie: Et mere elegant mønster kunne være Get(Value)?|Set(Value)?. Her gør ? 'Value' valgfrit. Da ? også er grådig, vil den forsøge at matche 'Value' hvis muligt, hvilket fører til det korrekte, længere match.
  • Brug ordgrænser: Den bedste løsning er ofte at specificere, at du kun vil matche hele ord: \b(Get(Value)?|Set(Value)?)\b. Dette sikrer, at du ikke matcher 'Set' i 'Settings'.

Det er værd at bemærke, at nogle motorer, især dem der følger POSIX-standarden, er 'tekst-styrede'. Disse motorer returnerer altid det længst mulige match og er ikke påvirket af rækkefølgen af alternativer. Dog kan dette føre til dårligere ydeevne, da motoren skal undersøge alle muligheder, før den returnerer et resultat.

Praktisk Behandling: Validering af Tidsformater

Lad os anvende vores viden på et praktisk eksempel: validering af tid i tt:mm format (00:00 til 23:59). En simpel tilgang som \d{2}:\d{2} er for upræcis, da den ville tillade '99:99'.

For at validere timer (00-23) kan vi bruge alternation. En time kan være enten et tal fra 00-19 eller et tal fra 20-23. Vi kan udtrykke dette således:

  • [01]\d: Matcher et 0 eller 1 efterfulgt af et hvilket som helst ciffer (00-19).
  • 2[0-3]: Matcher et 2 efterfulgt af et ciffer fra 0 til 3 (20-23).

Kombineret med alternation bliver det: [01]\d|2[0-3].

What are alternation constructs in net?
Alternation constructs modify a regular expression to enable either/or or conditional matching. . NET supports three alternation constructs: You can use the vertical bar (|) character to match any one of a series of patterns, where the | character separates each pattern.

For minutter (00-59) er mønsteret simplere: [0-5]\d.

Nu kombinerer vi dem: [01]\d|2[0-3]:[0-5]\d. Men her opstår det samme præcedensproblem som før! Motoren læser det som "match enten [01]\d ELLER 2[0-3]:[0-5]\d". Dette er forkert. Vi skal igen anvende gruppering.

Den korrekte og sunde recept er: ([01]\d|2[0-3]):[0-5]\d. Med parenteserne på plads sikrer vi, at alternationen kun gælder for time-delen, og hele udtrykket fungerer nu som forventet, og matcher kun gyldige tidsformater som '09:30' og '22:45', mens '30:61' ignoreres.

Sammenligning af Alternations-strategier

MetodeEksempelBedst til...Potentiel Bivirkning
Simpel Alternationkat|hundSimple, separate valg, hvor kontekst er irrelevant.Lav præcedens kan føre til utilsigtede matches, hvis den ikke grupperes.
Grupperet Alternation\b(kat|hund)\bAt begrænse 'enten/eller'-logikken til en specifik del af et større mønster.Opretter en 'capturing group', hvilket kan være unødvendigt (brug (?:...) for en non-capturing group).
Omarrangeret RækkefølgeSetValue|SetNår alternativer overlapper, og du vil sikre, at det mest specifikke match fanges først.Kan blive svært at vedligeholde og er afhængigt af motorens implementering.

Avanceret Terapi: Betinget Matching

For virkelig komplekse diagnoser tilbyder nogle regex-varianter, som .NET, en avanceret form for alternation kaldet betinget matching. Dette er en 'hvis-så-ellers'-struktur inde i selve regex-mønsteret. Syntaksen ser typisk sådan ud: (?(if)then|else).

Her er if et udtryk eller en reference til en 'capture group'. Hvis if-betingelsen er opfyldt, forsøger motoren at matche then-mønsteret. Hvis ikke, forsøger den at matche det valgfrie else-mønster.

Forestil dig, at du skal matche enten et amerikansk CPR-nummer (format: ddd-dd-dddd) eller et CVR-nummer (format: dd-ddddddd). Med en betinget konstruktion kan du lave et intelligent mønster, der tilpasser sig. For eksempel: \b(?(?=\d{3}-)\d{3}-\d{2}-\d{4}|\d{2}-\d{7})\b. Her tjekker (?=\d{3}-) (en 'lookahead'), om de næste tegn er tre cifre og en bindestreg. Hvis ja, matcher den CPR-nummerformatet; hvis nej, forsøger den at matche CVR-nummerformatet. Dette er avanceret medicin, men utroligt effektivt til at håndtere mønstre, der deler en kontekst, men har forskellig struktur.

How do I use alternation?
Alternation is similar. You can use alternation to match a single regular expression out of several possible regular expressions. If you want to search for the literal text cat or dog, separate both options with a vertical bar or pipe symbol: cat|dog. If you want more options, simply expand the list: cat|dog|mouse|fish.

Ofte Stillede Spørgsmål (OSS)

Hvad er den største fejl, folk begår med alternation?

Den absolut mest almindelige fejl er at glemme parenteser () til gruppering. På grund af |-operatorens lave præcedens vil den ofte 'lække' og påvirke hele udtrykket i stedet for kun den del, du havde til hensigt. Husk altid at indkapsle dine alternativer i parenteser, hvis de er en del af et større mønster.

Betyder rækkefølgen af mine valg noget?

Ja, i de fleste moderne regex-motorer gør den. Disse motorer er 'grådige' og stopper ved det første succesfulde match i din alternationsliste. Derfor bør du altid placere de længste og mest specifikke alternativer først for at undgå delvise matches (f.eks. `SetValue|Set` i stedet for `Set|SetValue`).

Kan jeg bruge alternation til mere end bare simple ord?

Absolut. Styrken ved alternation ligger i dens evne til at vælge mellem hele undermønstre, som kan være vilkårligt komplekse. Du kan have en alternation mellem et mønster for e-mailadresser og et mønster for telefonnumre i det samme udtryk. F.eks.: (\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b|\b\d{2}[- ]?\d{2}[- ]?\d{2}[- ]?\d{2}\b).

Hvordan adskiller `|` sig fra en tegnklasse som `[ae]`?

En tegnklasse som [ae] matcher et enkelt tegn, som enten kan være 'a' eller 'e'. Alternation, a|e, gør det samme i dette simple tilfælde. Forskellen bliver tydelig, når du arbejder med mere end ét tegn. gr[ae]y matcher 'gray' eller 'grey'. (gray|grey) gør det samme. Men du kan ikke udtrykke kat|hund med en tegnklasse, da det involverer hele sekvenser af tegn, ikke kun et enkelt tegnvalg.

At mestre alternation er som at lære at stille en præcis diagnose. Det giver dig mulighed for at se ud over de simple symptomer og skrive robuste, effektive og sunde regulære udtryk, der præcist løser dine databehandlingsproblemer. Ved at forstå dens præcedens, motorens adfærd og den korrekte brug af gruppering, har du den rette recept til at kurere mange almindelige 'kode-sygdomme'.

Hvis du vil læse andre artikler, der ligner Regex Alternation: Din Digitale Recept, kan du besøge kategorien Teknologi.

Go up