CodeKitHub
Regex greedy vs. lazy matching: hvorfor dit mønster fanger for meget

Regex greedy vs. lazy matching: hvorfor dit mønster fanger for meget

Udgivet 24. jul. 2026

Du skriver <b>.*</b> for at fange indholdet i et fed-tag, tester det på <b>Hello</b>, og det virker perfekt. Så kører du det på rigtig HTML med to fed-tags på samme linje — <b>Hello</b> and <b>World</b> — og i stedet for to matches får du ét kæmpe match, der spænder over begge tags. Det her er ikke en fejl i din regex-motor; det er standardopførslen for *, + og {n,m}, og der er en løsning på ét tegn, når du først ved, hvad der sker.

Hvorfor .* fanger mere, end du forventer

Som standard er kvantorer i regex grådige (greedy).* betyder ikke “match nogle tegn”, det betyder “match så mange tegn som muligt, og træk kun i land, hvis resten af mønstret absolut kræver det.”

Følg <b>.*</b> mod <b>Hello</b> and <b>World</b> trin for trin:

  1. <b> matcher det første <b>.
  2. .* starter med at sluge hele resten af strengen — alt frem til slutningen, inklusive det andet <b>World</b>.
  3. Motoren skal derefter finde </b> for at fuldføre matchet, så den begynder at trække sig tilbage fra slutningen af .* ét tegn ad gangen.
  4. Det første sted (set baglæns fra slutningen), hvor </b> passer, er det allersidste </b> i strengen — ikke det første, den “logisk” burde stoppe ved.

Så matchet ender med at være hele <b>Hello</b> and <b>World</b>, fordi grådig matching altid først prøver den længst mulige streng og kun formindsker den lige akkurat nok til at resten af mønstret lykkes.

Løsningen: gør kvantoren doven med ?

Hvis du tilføjer et ? lige efter en kvantor, vender den fra grådig til doven (lazy) (også kaldet “non-greedy” eller “reluctant”): *?, +?, ??, {n,m}?.

En doven kvantor gør det modsatte: den starter med at matche så få tegn som muligt, og udvider kun, hvis resten af mønstret endnu ikke kan lykkes.

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

  1. <b> matcher det første <b>.
  2. .*? starter med at matche nul tegn.
  3. Motoren tjekker: matcher </b> lige her? Nej (vi er ved “Hello…”, ikke ved et </b> endnu) — så udvider den .*? med præcis ét tegn og tjekker igen.
  4. Det gentages tegn for tegn, indtil .*? har slugt præcis Hello, hvorefter </b> matcher med det samme.

Resultat: <b>Hello</b> og <b>World</b> kommer tilbage som to separate matches, hvilket næsten altid er det, du faktisk ville have, når du parser tag-lignende eller afgrænser-lignende strukturer.

Hvornår du faktisk vil have grådig (det er ikke bare “den forkerte standard”)

Grådig er ikke en fejl i sproget — det er korrekt til et andet, lige så almindeligt tilfælde: at matche den yderste grænse af noget, ikke den mindste enhed indeni. Hvis du udtrækker “alt mellem den første { og den sidste }” i en blob af JSON-lignende tekst (fx for at fange et helt objekt uanset indlejring), er grådig præcis rigtigt, og doven ville i stedet stoppe ved den første indre } og give dig et afkortet, ugyldigt fragment.

Tommelfingerreglen: doven til gentagne små afgrænsede stykker (tags, citerede strenge, listeelementer); grådig til “fang hele det ydre spænd.”

Hurtig oversigt

Mønster Opførsel Brug det når
.*, .+, {n,m} Grådig — matcher længst mulig Du vil have det yderste spænd, eller der kun er ét match i strengen
.*?, .+?, {n,m}? Doven — matcher kortest mulig Du har flere lignende afgrænsede stykker og vil have hvert enkelt for sig

Hvis du er i tvivl om, hvad et mønster faktisk gør på dit rigtige input frem for din teststreng, gør det at køre det mod den faktiske multi-match-tekst i en regex tester med live match-fremhævning forskellen øjeblikkeligt synlig — du vil se én kæmpe fremhævet blok for grådig versus flere separate for doven, hvilket som regel er hurtigere end at ræsonnere sig frem tegn for tegn.

← Tilbage til bloggen