How to capture all phrases which doesn't have a pattern in the middle of theirself?

Viewed 33

I want to capture all strings that doesn't have the pattern: a[a-z]*

<?php 

$myStrings = array(
  "123-456",
  "123-7-456",
  "123-Apple-456",
  "123-0-456",
  "123-Alphabet-456"
);

foreach($myStrings as $myStr){
  echo var_dump(
    preg_match("/123-(?!a[a-z]*)-456/i", $myStr)
  );
}

?>
3 Answers

Match the pattern and invert the result:

!preg_match('/a[a-z]*/i', $yourStr);

Don't try to do everything with a regex when programming languages exist to do the job.

A lookahead is a zero-length assertion. The middle part also needs to be consumed to meet 456. For consuming use e.g. \w+- for one or more word characters and hyphen inside an optional group that starts with your lookahead condition. See this regex101 demo (i flag for caseless matching).

Further for searching an array preg_grep can be used (see php demo at tio.run).

preg_grep('~^123-(?:(?!a[a-z]*-)\w+-)?456$~i', $myStrings);

There is also an invert option: PREG_GREP_INVERT. If you don't need to check for start and end a more simple pattern like -a[a-z]*- without lookahead could be used (another php demo).

You can check the following solution at this Regex101 share link.

^(123-(?:(?![aA][a-zA-Z]*).*)-456)|(123-456)$

It uses regex non-capturing group (?:) and regex negative lookahead (?!) to find all inner sections that do not start with 'a' (or 'A') and any letters after that. Also, the case with no inner section (123-456) is added (with the | sign) as a 2nd alternative for a wrong pattern.

Related