5

Is there a way (other than by doing two separate pattern matches) to use preg_match in PHP to test for either the beginning of the string or a pattern? More specifically I often find myself wanting to test that I have a matching pattern which is not preceded by something, as in

preg_match('/[^x]y/', $test)

(that is, match y if it is not preceded by x), but to also match y if it occurs at the start of $test (when it also isn't preceded by x, but isn't preceded by any character, so the [^x] construct won't work as it always requires a character to match it.

There's a similar problem at the end of strings, to determine whether a pattern occurs that is not followed by some other pattern.

frankieandshadow
  • 561
  • 6
  • 14
  • Also this: http://stackoverflow.com/questions/3092797/how-does-the-regular-expression-work – Kobi May 09 '13 at 11:04

3 Answers3

10

You can simply use standard alternation syntax:

/(^|[^x])y/

This will match a y that is preceded either by the start of the input or by any character other than x.

Of course in this specific instance, where the alternative to the ^ anchor is so simple, you can also very well use negative lookbehind:

/(?<!x)y/
Jon
  • 428,835
  • 81
  • 738
  • 806
1
$name = "johnson";
preg_match("/^jhon..n$/",$name);

^ is locates to starting and $ is locates to ending of string

VladL
  • 12,769
  • 10
  • 63
  • 83
Mak Ashtekar
  • 154
  • 1
  • 11
0
    You need following negate rules:-

--1--^(?!-) is a negative look ahead assertion, ensures that string does not start with specified chars

--2--(?<!-)$ is a negative look behind assertion, ensures that string does not end with specified chars

Say you want to have staring that doesn't start with 'start' and end with 'end' strings:-

Your Pattern is  :

$pattern = '/^(?!x)([a-z0-9]+)$(?

 $pattern = '/^(?!start)([a-z0-9]+)$(?<!end)/';

$strArr = array('start-pattern-end','allpass','start-pattern','pattern-end');


 foreach($strArr as $matstr){ 
     preg_match($pattern,$matstr,  $matches);
     print_R( $matches);
 }

This will output :allpass only as it doen't start with 'start' and end with 'end' patterns.
deepika jain
  • 363
  • 3
  • 7