0

更新:实际上 php 不支持可变长度的lookbehind。这种方法在 php.ini 中是不可能的。任何可变长度的lookbehind都会给出错误“编译失败:lookbehind断言不是固定长度”

我有以下正则表达式(我正在使用 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

提前致谢。

4

1 回答 1

1

你的lookbehind没有很好地形成。后视中的“或”条件(在 PHP 中的括号内使用时)需要相同的长度。否则,您可以像在

$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);
于 2013-01-28T01:29:56.287 回答