匹配正则表达式,如果没有前面的某些单词

时间:2013-01-27 23:42:46

标签: php regex

更新:实际上php不支持可变长度的lookbehind。这种方法在php中是不可能的。任何可变长度的lookbehind都会出现错误“Compilation failed:lookbehind assertion is not fixed length”

我有以下正则表达式(我正在使用php):

/\d{2}\s\b(ans|year|years|sana|años|anos|sna)\b/i

匹配以下模式:

22 years
49 ans
98 anos

如果输入前面有某些单词(“since”,“depuis”等),我需要使它不匹配

所以:

I'm 22 years
I have 49 years

会匹配,而:

Since 19 years
Depuis 10 ans

不匹配

我试过这个,没有效果:

/(?<!(depuis|since|monz))\d{2}\s\b(ans|year|years|sana|años|anos|sna)\b/i

提前致谢。

1 个答案:

答案 0 :(得分:1)

你的外观形象不佳。 lookbehinds中的“或”条件(在PHP中用于parens时)需要相同的长度。否则你可以像

一样逐个编写整个lookbehind条件
$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);

[编辑2]

最后一个单词和所需部分之间可能存在多个空格(如下面评论中的@nhahtdh)。虽然这不是一个单一的模式,但你可以避免这种情况。

$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);