Reputation: 1226
Update : Actually php does not support lookbehind with variable lengths. This approach is not possible in php. Any variable length lookbehind will give an error "Compilation failed: lookbehind assertion is not fixed length"
I have the following regex (i'm using php) :
/\d{2}\s\b(ans|year|years|sana|años|anos|sna)\b/i
that matches patterns like :
22 years
49 ans
98 anos
I need to cause it to not match if the input is preceeded by certain words ("since", "depuis", etc)
so :
I'm 22 years
I have 49 years
would match, while :
Since 19 years
Depuis 10 ans
would not match.
I've tried this, to no effect :
/(?<!(depuis|since|monz))\d{2}\s\b(ans|year|years|sana|años|anos|sna)\b/i
Thanks in advance.
Upvotes: 0
Views: 273
Reputation: 7470
Your lookbehind is not well formed. The "or" conditon in lookbehinds (when used inside parens in PHP) requires same length. Otherwise you can just write the whole lookbehind conditions one by one like in
$str = "I'm 22 years and I have 49 years but Since 19 years and Depuis 10 ans";
preg_match_all(
'~
(?<!
\bdepuis\s |
\bsince\s |
\bmonz\s
)
\d{2}\s
(?:
ans? |
years? |
sana |
años? |
anos? |
sna
)\b
~xi',$str,$m);
print_r($m);
There's a chance that there might be multiple empty spaces between the last word and the desired part (like @nhahtdh wrote below in the comments). Although this is not a single pattern here's how you can avoid such situations.
$pat =
'~
(
(?(?<=^)(?=\s*) # if it is the beginning of the string
(?:\s*) # match possible spaces
| # otherwise match
(?:
(?<=\s) # following a space,
(?: # a word that is not listed below
(?!(?:
depuis |
since |
monz
))
\S
)+
\s+ # and 1 or more spaces
)
)
)
\d{2}\s+ # then your pattern itself
(?:
ans? |
years? |
sana |
años? |
anos? |
sna
)\b
~xi';
preg_match_all($pat,$str,$matches);
foreach ($matches[0] as $k => &$v)
// replace the previous word if any
$v = substr($v,strlen($matches[1][$k]));
// and delete the reference
unset($v);
print_r($matches);
Upvotes: 1