It's almost impossible to answer this without having some idea of what the separator can be -- which characters, how many characters, etc. A non-greedy arbitrary separator would look like this:
s/\b1001\b(?=.*?\bjohn\b)/2001/
This replaces "1001" when followed by "john" while matching the minimum number of intermediate characters. .*?
is the non-greedy version of .*
. However, regexes always match if possible so this would still match
1001-mark-1001-john
In other words, it's not just a greediness problem. We need to define at least one of three things:
- The characters the separator can contain.
- The characters the separator cannot contain.
- The number of characters in the separator.
If we assume that the separator cannot contain "word" characters (a-z, 0-9, and underscore) we can get something workable:
s/\b1001\b(?=\W+?\bjohn\b)/2001/
The known parts ("1001" and "john") are bounded to prevent them from matching other strings with these substrings. (Thanks to Chas for noticing that edge case.)