
[Tim, on trying to match only the next instance of "spam"]
Assertions aren't needed, but it is nightmarish to get right.
Followed by a nightmare that got it wrong. My apologies - that's what I get for trying to show off ;-) It's actually far easier if assertions are used, and I'm too old to bother trying to repair the non-assertion mess: ([^s]|s(?!pam))*spam Bingo. That pattern is easy enough to understand (if not to invent the first time): we can chew up a character if it's not an "s", or if it is an "s" but one _not_ followed immediately by "pam". The "s" at the start of a matched "spam" doesn't satisfy either alternative, so it can't go beyond the leftmost following "spam". Of course the same trick can be used to find just the next occurrence of any fixed string of at least two characters.