【问题标题】:Are the PHP preg_functions multibyte safe?PHP preg_functions 多字节安全吗?
【发布时间】:2010-12-18 11:58:01
【问题描述】:

PHP 中没有可用的多字节“preg”函数,这是否意味着默认的 preg_functions 都是 mb 安全的?在 php 文档中找不到任何提及。

【问题讨论】:

  • 我 90% 确定底层 C 函数是,但这并不意味着我认为 PHP 版本是...

标签: php preg-replace preg-match multibyte


【解决方案1】:

不,他们不是。例如,请参阅问题preg_match and UTF-8 in PHP

【讨论】:

  • 为了澄清,PREG_OFFSET_CAPTURE 产生字节偏移而不是字符偏移。它与 PHP 中的字符串处理是一致的,但它可能会很混乱。
  • 如果你使用T-Regx tool,你可以使用offset()byteOffset()方法来获取字符或字节的偏移量。
【解决方案2】:

不,你需要像mb_ereg一样使用multibyte string functions

【讨论】:

  • 它们是 POSIX ereg 函数的多字节版本,但与 PCRE preg 函数并不完全相同。
  • Ben S 你是我的英雄 :) 我只是想净化文本并将 äöüß 留在文本中。 preg_replace 从来没有正确地做到这一点,但 mb_ereg 做到了!
  • 只要您使用 /u 修饰符,它们就是多字节安全的,只要多字节编码是 UTF-8。 /u 引擎不支持 UTF-8 以外的任何其他编码
  • preg_match/u 修饰符效果很好!谢谢@hanshenrik
【解决方案3】:

PCRE 可以支持 UTF-8 和其他 Unicode 编码,但必须在编译时指定。来自man page for PCRE 8.0

PCRE 的当前实现与 Perl 5.10 大致对应,包括对 UTF-8 编码字符串和 Unicode 通用类别属性的支持。但是,必须明确启用 UTF-8 和 Unicode 支持;它不是默认值。 Unicode 表对应于 Unicode 版本 5.1。

PHP 目前使用PCRE 7.9;您的系统可能有旧版本。

查看 PHP 5.2 附带的 PCRE lib,它似乎已配置为支持 Unicode 属性和 UTF-8。 5.3 branch 也一样。

【讨论】:

  • 我正在使用包含 PCRE 版本 7.9 的 PHP 5.3.0,我检查了包含 UTF8 定义的 PCRE config.h 文件,所以看起来 preg_funcs 是安全的。非常感谢您提供的信息!
  • 有没有一种快速的方法来确定现有 PHP 安装使用的是哪个版本的 PCRE?例如,我的服务器运行的是 PHP 5.5,但我如何知道它是用什么 PCRE 库编译的?
【解决方案4】:

pcre 支持 utf8 开箱即用,请参阅 'u' 修饰符的文档。

插图(\xC3\xA4 是德语字母“ä”的 utf8 编码)

  echo preg_replace('~\w~', '@', "a\xC3\xA4b");

这与“@@¤@”相呼应,因为“\xC3”和“\xA4”被视为不同的符号

  echo preg_replace('~\w~u', '@', "a\xC3\xA4b");

(注意“u”)打印“@@@”,因为“\xC3\xA4”被视为单个字母。

【讨论】:

  • 真的吗?嗯,我对正则表达式字符串并不太精通,如果你不介意我可能会发布一些我的 preg_ 代码来看看你的想法?
  • 非常适合 u 修饰符,我不知道
  • 我在调用preg_replacejson_encode 处理字符串时出错,但由于preg_replace 将一些UTF-8 字符转换为替换字符 而失败。 u 修饰符拯救了我的一天!!!非常感谢。
【解决方案5】:

我的一些更复杂的 preg 函数:

(1a) 验证用户名是否为字母数字 + 下划线:

preg_match('/^[A-Za-z][A-Za-z0-9]*(?:_[A-Za-z0-9]+)*$/',$username) 

(1b) 可能的 UTF 替代方案:

preg_match('/^[A-Za-z][A-Za-z0-9]*(?:_[A-Za-z0-9]+)*$/u',$username) 

(2a) 验证电子邮件:

preg_match("/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/ix",$email))

(2b) 可能的 UTF 替代方案:

preg_match("/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/ixu",$email))

(3a) 规范换行:

preg_replace("/(\n){2,}/","\n\n",$str);

(3b) 可能的 UTF 替代方案:

preg_replace("/(\n){2,}/u","\n\n",$str);

这些变化看起来好吗?

【讨论】:

  • 我相信您的电子邮件正则表达式将允许电子邮件地址中的任何位置出现“..”,这是您需要断言来防止的事情。
猜你喜欢
  • 2014-12-12
  • 2012-01-23
  • 2015-10-12
  • 2013-05-27
  • 1970-01-01
  • 2014-12-14
  • 2017-07-06
  • 1970-01-01
相关资源
最近更新 更多