2

I want my regex to match ?ver and ?v, but not ?version

This is what I have so far: $parts = preg_split( "(\b\?ver\b|\b\?v\b)", $src );

I think the trouble might be how I escape the ?.

mickmackusa
  • 43,625
  • 12
  • 83
  • 136
Fjott
  • 1,107
  • 3
  • 15
  • 38

3 Answers3

7

Your pattern tries to match a ? that is preceded with a word char, and since there is none, you do not have a match.

Use the following pattern:

'/\?v(?:er)?\b/'

See the regex demo

Pattern details:

  • \? - a literal ? char
  • v(?:er)? - v or ver
  • \b - a word boundary (i.e. there must be a non-word char (not a digit, letter or _) or end of string after v or ver).

Note you do not need the first (initial) word boundary as it is already there, between a ? (a non-word char) and v (a word char). You would need a word boundary there if the ? were optional.

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
5

Try the following regex pattern;

(\?v(?:\b|(?:er(?!sion))))

Demo

This will allow ?ver and ?v, but will use a negative look-ahead to prevent matching if ?ver is followed by sion, as in your case ?version.

Tom Wyllie
  • 2,020
  • 13
  • 16
  • How do you know the targeted substring terminates at the end of line? Your pattern could actually be incorrect, but we will not know until the OP provides some sample strings. This is not a concern for Wiktor's correct pattern. – mickmackusa Jul 18 '17 at 13:04
  • OP did provide sample strings - he said "I want my regex to match `?ver` and `?v`, but not `?version`". – Tom Wyllie Jul 18 '17 at 13:20
  • However, on the off-chance that that is what OP meant and they didn't articulate it very well, I've edited my answer now as it comes at no cost to the original solution. Thanks for pointing that out! :) – Tom Wyllie Jul 18 '17 at 13:20
  • Now that you understand the requirement for a word boundary, your answer is now a less efficient version of Wiktor's answer and is not useful. You did not attempt to optimize your pattern and so you are not showing users a refined pattern. `\?v(?:\b|(?:er(?!sion)))` and `\?v(?:\b|er(?!sion))` are more efficient versions of your posted pattern. – mickmackusa Jul 18 '17 at 20:52
1

Building upon above answers, to match a word without being a part of another you can try \b(WORD_HERE)\b which in your case is \b(\?ver)\b this will allow ver and prevent version average

Hassan Amin
  • 142
  • 1
  • 5
  • Why using a capture group? The word boundary before `\?` is useless and can cause wrong match if it is positionned at the beginning of the string or if there are spaces before (i.e. it will no match the string `?ver` [Demo](https://regex101.com/r/BQDhcA/1) – Toto Nov 16 '19 at 11:01