An attempt at being thorough and complete. Mainly for my own benefit.

Most pages about regexes mention `+`

and `*`

as the greedy ones and `+?`

and `*?`

as their lazy equivalents. However, there are more combinations of quantifiers that can be distinguished into lazy and greedy variants. So here we go.

greedy | lazy | example |
---|---|---|

+ | +? | X+ matches all X’s in XXXYYY X+? matches the first X in XXXYYY |

This is rather straightforward: `+` matches one or more of the preceding, so `X+` matches all X’s and `X+?` matches just one X.JavaScript example: `'XXXYYY'.replace(/X+/, 'o')` results in `oYYY` `'XXXYYY'.replace(/X+?/, 'o')` results in `oXXYYY` |
||

greedy | lazy | example |

* | *? | X* matches all X’s in XXXYYY X*? matches the empty string at the start of XXXYYY |

Pretty much the same as above: `*` matches zero or more of the preceding, so `X*` matches all X’s and `X*?` matches just zero X’s, that is, nothing.JavaScript example: `'XXXYYY'.replace(/X*/, 'o')` results in `oYYY` `'XXXYYY'.replace(/X*?/, 'o')` results in `oXXXYYY` |
||

greedy | lazy | example |

? | ?? | X? matches the first X in XXXYYY X?? matches the empty string at the start of XXXYYY |

`?` matches zero or one of the preceding, so `X?` matches the first X and `X??` matches no X, or nothing.JavaScript example: `'XXXYYY'.replace(/X?/, 'o')` results in `oXXYYY` `'XXXYYY'.replace(/X??/, 'o')` results in `oXXXYYY` |
||

greedy | lazy | example |

{n,m} | {n,m}? | X{2,3} matches the first three X’s in XXXYYY X{2,3}? matches the first two X’s in XXXYYY |

This may not be as familiar to some, but it works in the same way: `X{n,m}` matches at least n and at most m X’s, so `X{2,3}` matches three X’s (if possible), while `X{2,3}?` matches only two (if possible).JavaScript example: `'XXXYYY'.replace(/X{2,3}/, 'o')` results in `oYYY` `'XXXYYY'.replace(/X{2,3}?/, 'o')` results in `oXYYY` |
||

greedy | lazy | example |

.. | | | .. | X| matches the first X in XXXYYY |X matches the empty string at the start of XXXYYY |

And somewhat unexpected maybe, but the logical “or” operator can be used with the empty string as one of its choices, and the result depends on whether you put the empty string first or last; it checks from left to right. So `X|` matches an X (if there is one), and `|X` matches the empty string.JavaScript example: `'XXXYYY'.replace(/X|/, 'o')` results in `oXXYYY` `'XXXYYY'.replace(/|X/, 'o')` results in `oXXXYYY` |

That’s all the ones I can think of. If anybody knows of more constructs that can be used in both a greedy and a lazy manner, comment below and I’ll update this.