代码之家  ›  专栏  ›  技术社区  ›  tomsv

php regex单词边界匹配(utf-8)

  •  12
  • tomsv  · 技术社区  · 16 年前

    我在utf-8 php文件中有以下php代码:

    var_dump(setlocale(LC_CTYPE, 'de_DE.utf8', 'German_Germany.utf-8', 'de_DE', 'german'));
    var_dump(mb_internal_encoding());
    var_dump(mb_internal_encoding('utf-8'));
    var_dump(mb_internal_encoding());
    var_dump(mb_regex_encoding());
    var_dump(mb_regex_encoding('utf-8'));
    var_dump(mb_regex_encoding());
    var_dump(preg_replace('/\bweiß\b/iu', 'weiss', 'weißbier'));
    

    我希望最后一个regex只替换完整的单词,而不是部分单词。

    在我的Windows计算机上,它返回:

    string 'German_Germany.1252' (length=19)
    string 'ISO-8859-1' (length=10)
    boolean true
    string 'UTF-8' (length=5)
    string 'EUC-JP' (length=6)
    boolean true
    string 'UTF-8' (length=5)
    string 'weißbier' (length=9)
    

    在Web服务器(Linux)上,我得到:

    string(10) "de_DE.utf8"
    string(10) "ISO-8859-1"
    bool(true)
    string(5) "UTF-8"
    string(10) "ISO-8859-1"
    bool(true)
    string(5) "UTF-8"
    string(9) "weissbier"
    

    因此,regex在Windows上可以像我预期的那样工作,但在Linux上却不行。

    所以主要的问题是,我应该如何编写只在单词边界匹配的regex?

    第二个问题是如何让Windows知道我想在PHP应用程序中使用UTF-8。

    4 回复  |  直到 16 年前
        1
  •  17
  •   Alan Moore Chris Ballance    10 年前

    即使是在UTF-8模式下,标准类速记员 \w \b 不支持Unicode。您只需要使用Unicode速记,正如您所了解的那样,但是您可以通过使用lookarounds而不是alternations使其不那么难看:

    /(?<!\pL)weiß(?!\pL)/u
    

    还请注意我如何将花括号从unicode类速记中去掉;当类名由单个字母组成时,您可以这样做。

        2
  •  4
  •   tomsv    16 年前

    这是我迄今为止发现的。通过这样重写搜索和替换模式:

    $before = '(^|[^\p{L}])';
    $after = '([^\p{L}]|$)';
    var_dump(preg_replace('/'.$before.'weiß'.$after.'/iu', '$1weiss$2', 'weißbier'));
    // Test some other cases:
    var_dump(preg_replace('/'.$before.'weiß'.$after.'/iu', '$1weiss$2', 'weiß'));
    var_dump(preg_replace('/'.$before.'weiß'.$after.'/iu', '$1weiss$2', 'weiß bier'));
    var_dump(preg_replace('/'.$before.'weiß'.$after.'/iu', '$1weiss$2', ' weiß'));
    

    我得到了想要的结果:

    string 'weißbier' (length=9)
    string 'weiss' (length=5)
    string 'weiss bier' (length=10)
    string ' weiss' (length=6)
    

    在运行Apache的Windows计算机和运行Apache的托管Linux Web服务器上。

    我想有更好的方法可以做到这一点。

    另外,我仍然希望将我的Windows计算机设置为UTF-8。

        3
  •  4
  •   bobble bubble    9 年前

    我猜这和 Bug #52971

    PCRE元字符,如 \b \w 不使用Unicode字符串。

    fixed in PHP 5.3.4

    PCRE扩展: 修正了错误52971 ( PCRE元字符不使用UTF-8 )

        4
  •  0
  •   ntd    16 年前

    根据 this comment ,这是PHP中的一个错误。是否使用 \W 而不是 \b 有什么好处吗?

    推荐文章