CodeKitHub
Grådig vs. lat matching i regex: hvorfor mønsteret ditt griper for mye

Grådig vs. lat matching i regex: hvorfor mønsteret ditt griper for mye

Publisert 24. juli 2026

Du skriver <b>.*</b> for å hente ut innholdet i en fet-tekst-tag, tester den på <b>Hello</b>, og den fungerer perfekt. Så kjører du den på ekte HTML med to fet-tekst-tagger på samme linje — <b>Hello</b> and <b>World</b> — og i stedet for to treff får du ett kjempetreff som spenner over begge taggene. Dette er ikke en feil i regex-motoren din; det er standardoppførselen til *, + og {n,m}, og det har en løsning på ett tegn når du vet hva som skjer.

Hvorfor .* griper mer enn du forventer

Som standard er kvantifikatorer i regex grådige.* betyr ikke «match noen tegn», det betyr «match så mange tegn som mulig, og trekk deg bare tilbake hvis resten av mønsteret absolutt krever det».

Gå gjennom <b>.*</b> mot <b>Hello</b> and <b>World</b> steg for steg:

  1. <b> matcher den første <b>.
  2. .* starter med å konsumere hele resten av strengen — alt frem til slutten, inkludert den andre <b>World</b>.
  3. Motoren må så finne </b> for å fullføre matchen, så den begynner å trekke seg tilbake fra slutten av .* ett tegn av gangen.
  4. Det første stedet (sett bakover fra slutten) der </b> passer, er den aller siste </b> i strengen — ikke den første den «logisk» burde stoppet ved.

Så treffet ender opp med å bli <b>Hello</b> and <b>World</b> i sin helhet, fordi grådig matching alltid prøver den lengst mulige strengen først og bare krymper den så lite som nødvendig for at resten av mønsteret skal lykkes.

Løsningen: gjør kvantifikatoren lat med ?

Å legge til et ? rett etter en kvantifikator snur den fra grådig til lat (også kalt «non-greedy» eller «reluctant»): *?, +?, ??, {n,m}?.

En lat kvantifikator gjør det motsatte: den starter med å matche så få tegn som mulig, og utvider seg bare hvis resten av mønsteret ikke kan lykkes ennå.

<b>.*?</b> mot samme streng:

  1. <b> matcher den første <b>.
  2. .*? starter med å matche null tegn.
  3. Motoren sjekker: matcher </b> akkurat her? Nei (vi er ved «Hello…», ikke ennå ved en </b>) — så den utvider .*? med nøyaktig ett tegn og sjekker igjen.
  4. Dette gjentas tegn for tegn helt til .*? har konsumert nøyaktig Hello, hvorpå </b> matcher umiddelbart.

Resultat: <b>Hello</b> og <b>World</b> kommer tilbake som to separate treff, som nesten alltid er det du faktisk ønsket når du parser tag-lignende eller skilletegn-lignende strukturer.

Når du faktisk vil ha grådig (det er ikke bare «feil standard»)

Grådig er ikke en feil i språket — det er riktig for et annet, like vanlig tilfelle: å matche den ytterste grensen av noe, ikke den minste enheten inni det. Hvis du henter ut «alt mellom den første { og den siste }» i en blob med JSON-lignende tekst (for eksempel for å gripe et helt objekt uansett nøsting), er grådig akkurat riktig, og lat ville stoppet ved den første indre } i stedet, og gitt deg et avkuttet, ugyldig fragment.

Tommelfingerregelen: lat for gjentatte små avgrensede biter (tagger, tekst i anførselstegn, listeelementer); grådig for «grip hele det ytre spennet».

Hurtigreferanse

Mønster Oppførsel Bruk det når
.*, .+, {n,m} Grådig — matcher lengst mulig Du vil ha det ytterste spennet, eller det bare finnes ett treff i strengen
.*?, .+?, {n,m}? Lat — matcher kortest mulig Du har flere lignende avgrensede biter og vil ha hver av dem separat

Hvis du er usikker på hva et mønster faktisk gjør på din ekte input i stedet for teststrengen din, gjør det å kjøre det mot den faktiske teksten med flere treff i en regex-tester med live treff-utheving forskjellen umiddelbart synlig — du vil se én kjempeblokk utheves for grådig, mot flere separate for lat, noe som vanligvis er raskere enn å resonnere seg gjennom det tegn for tegn.

← Tilbake til bloggen