字符串损坏或 preg_match 错误?

2024-04-10

NO-BREAK SPACE 和许多其他 UTF-8 符号需要 2 个字节来表示 http://www.fileformat.info/info/unicode/char/a0/index.htm;因此,在假定的 UTF8 字符串上下文中,非 ASCII (>127) 的隔离(前面没有 xC2)字节是无法识别的字符...好吧,这只是一个布局问题(!),但是它破坏了整个字符串?

如何避免这种“非预期行为”? (它出现在某些函数中,而不出现在其他函数中 http://www.php.net/manual/en/language.types.string.php#language.types.string.details).

示例(生成非预期行为preg_match only):

  header("Content-Type: text/plain; charset=utf-8"); // same if text/html
  //PHP Version 5.5.4-1+debphp.org~precise+1
  //using a .php file enconded as UTF8.

  $s = "THE UTF-8 NO-BREAK\xA0SPACE"; // a non-ASCII byte
  preg_match_all('/[-\'\p{L}]+/u',$s,$m);
  var_dump($m);            // empty! (corrupted)
  $m=str_word_count($s,1);
  var_dump($m);            // ok

  $s = "THE UTF-8 NO-BREAK\xC2\xA0SPACE";  // utf8-encoded nbsp
  preg_match_all('/[-\'\p{L}]+/u',$s,$m);
  var_dump($m);            // ok!
  $m=str_word_count($s,1);
  var_dump($m);            // ok

这不是一个完整的答案,因为我没有说为什么有些 PHP 函数”无效编码的字符串完全失败“而其他人则不然:请参阅问题评论中的@deceze 和@hakre 答案。 如果您正在寻找 PCRE 替代品str_word_count(),看我的preg_word_count() below.

PS:关于“PHP5的内置库行为统一” 讨论,我的结论是 PHP5 还不错,但是我们创建了很多用户定义的包装(外观)函数(参见 PHP 框架的多样性!)...或者等待 PHP6 :-)


谢谢@pebbl!如果我理解你的链接,PHP 缺少错误消息 http://php.net/manual/en/reference.pcre.pattern.modifiers.php#54805。因此,我所图示的问题的一个可能的解决方法是添加一个错误条件......我发现这里的条件 https://stackoverflow.com/a/1523574/287948(它确保有效的utf8!)...并且感谢@deceze记住存在一个内置函数来检查这个条件(我之后编辑了代码)。

将问题放在一起,将解决方案转换为函数(已编辑,感谢 @hakre 评论!),

 function my_word_count($s,$triggError=true) {
   if ( preg_match_all('/[-\'\p{L}]+/u',$s,$m) !== false )
      return count($m[0]);
   else {
      if ($triggError) trigger_error(
         // not need mb_check_encoding($s,'UTF-8'), see hakre's answer, 
         // so, I wrong, there are no 'misteious error' with preg functions
         (preg_last_error()==PREG_BAD_UTF8_ERROR)? 
              'non-UTF8 input!': 'other error',
         E_USER_NOTICE
         );
      return NULL;
   }
 }

现在(在思考@hakre答案后编辑),关于统一的行为:我们可以使用 PCRE 库开发一个合理的函数来模仿str_word_count行为,接受错误的 UTF8。对于这个任务我使用了@bobinceiconv tip https://stackoverflow.com/a/1523574/287948:

 /**
  * Like str_word_count() but showing how preg can do the same.
  * This function is most flexible but not faster than str_word_count.
  * @param $wRgx the "word regular expression" as defined by user.
  * @param $triggError changes behaviour causing error event.
  * @param $OnBadUtfTryAgain mimic the str_word_count behaviour.
  * @return 0 or positive integer as word-count, negative as PCRE error.
  */
 function preg_word_count($s,$wRgx='/[-\'\p{L}]+/u', $triggError=true,
                          $OnBadUtfTryAgain=true) {
   if ( preg_match_all($wRgx,$s,$m) !== false )
      return count($m[0]);
   else {
      $lastError = preg_last_error();
      $chkUtf8 = ($lastError==PREG_BAD_UTF8_ERROR);
      if ($OnBadUtfTryAgain && $chkUtf8) 
         return preg_word_count(
            iconv('CP1252','UTF-8',$s), $wRgx, $triggError, false
         );
      elseif ($triggError) trigger_error(
         $chkUtf8? 'non-UTF8 input!': "error PCRE_code-$lastError",
         E_USER_NOTICE
         );
      return -$lastError;
   }
 }

展示(尝试其他输入 https://stackoverflow.com/a/19274144!):

 $s = "THE UTF-8 NO-BREAK\xA0SPACE"; // a non-ASCII byte
 print "\n-- str_word_count=".str_word_count($s,0);
 print "\n-- preg_word_count=".preg_word_count($s);

 $s = "THE UTF-8 NO-BREAK\xC2\xA0SPACE";  // utf8-encoded nbsp
 print "\n-- str_word_count=".str_word_count($s,0);
 print "\n-- preg_word_count=".preg_word_count($s);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

字符串损坏或 preg_match 错误? 的相关文章

随机推荐

  • android studio 3.1 中的模块:应用程序没有系统资源管理器

    android studio 3 1 中的模块 应用程序没有系统资源管理器 问题是 当它 android studio android 3 1 我不幸进入完成内置库文件后 它显示下载或刷新如果你已经下载 我使用下载之后这个错误来了 该文件名
  • type(myVar) 和 (type)myVar 有什么区别?

    我正在 cplusplus com 上阅读完整的教程 手动编码和编译每个示例 我经常会偶然发现一些让我困惑的事情 我目前正在学习这一部分 http www cplusplus com doc tutorial structs http ww
  • 安装带有 Capacitor 的 BackgroundGeolocation 插件后,无法在 Android 上构建 Ionic 应用程序

    我正在尝试将我的应用程序从 Cordova 迁移到 Capacitor 但我仍然需要使用后台地理定位等功能 为此 我正在使用这个插件 https ionicframework com docs native background geolo
  • 为什么 git 没有 pre-push hook?

    在将更改推送到远程 位于 bitbucket 上 之前 我希望有一个钩子来运行我的测试 我通常会从 master 分支出来 当该功能完成后 我会将其合并回 master 并推送 这就是我寻找预推送钩子的原因 相反 我使用了仅限于主分支的合并
  • 需要帮助在两个套接字之间创建 TCP 中继

    我有以下情况 SomeServer S lt gt C MyApp S lt gt C User S represents a server socket C represents a client socket 本质上 MyApp发起通信
  • 初始化后无法应用 JqueryUI 可调整 AspectRatio?

    我试图在 JQueryUI 可调整大小中动态打开 关闭纵横比 但是即使将选项设置为 false 后 它仍然保持纵横比 以下是我当前正在使用的代码 aspect check click function var ischecked aspec
  • Python setuptools:包目录不存在

    我有一个与此相关的项目setup py file import setuptools with open README md r as fh long description fh read setuptools setup name ve
  • mousemove 事件是否每帧触发一次?

    In this 小提琴演示 https jsfiddle net JoeZheng uy9poL1j 按下并移动鼠标会根据鼠标的位置绘制点 绘制方法是听mousemove回调 但它绘制了离散点 表明mousemove事件不会连续触发 更重要
  • 枚举值的类型[重复]

    这个问题在这里已经有答案了 我可以通过以下方式获取表示接口键的类型 interface I a string b string const i keyof I typeof i is a b 有没有办法类似地获取表示枚举值的类型 enum
  • 在 Dart 中实现观察者模式

    我想在 Dart 中实现观察者模式 但我不知道如何去做 假设我有一堂课 class MyClass String observed field 现在 每当我更改字段时 我都想将 observed fieldchanged 字符串打印到控制台
  • UIWebView 到 UIImage

    我尝试使用此方法从 UIWebView 捕获图像 但图像仅包含屏幕的可见区域 如何捕获 UIWebView 的完整内容 包括不可见区域 即整个网页到一张图像中 UIImage captureScreen UIView viewToCaptu
  • undefined 不是一个对象(评估route.routeName)

    when update the expo from 16 0 0 to 24 0 0 and react navigation from git https github com react community react navigati
  • 如何将UIView裁剪为半圆?

    我想将 UIView 裁剪为半圆形 提前致谢 一个方便的方法就是子类 aUIView 在其上添加一个图层 并使视图颜色透明 如果不是默认情况下 import UIKit class SemiCirleView UIView var semi
  • BaseX RESTXQ“你好世界”示例

    我正在努力开始使用基本 REST API 我已下载并安装了最新版本的 Windows 版 BaseX 我通过单击 BaseX 安装添加到 Windows 开始菜单中的 BaseX Server 开始 图标启动了 BaseX Server 看
  • node/express:使用Forever连续运行脚本时设置NODE_ENV

    我怎样才能设置NODE ENV http expressjs com guide html configuration当我使用时变量 参数为 生产 forever https github com indexzero forever启动我的
  • 如何利用 Android 的“清除缓存”按钮

    在 Android 的设置中 在 管理应用程序 活动中 单击应用程序时 数据会分解为应用程序 数据和缓存 还有一个清除缓存的按钮 我的应用程序缓存音频文件 我希望用户能够使用此按钮清除缓存 我如何存储它们 以便它们与缓存集中在一起并且用户可
  • 使用另一个域的用户凭据连接到 SQL Server

    如何使用另一个域中的用户登录名 密码连接到 SQL Server 数据库 如果我使用我的帐户连接到数据库 它工作正常 cnxn pyodbc connect DRIVER SQL Server SERVER server name DATA
  • Netbeans 错误:项目文件夹已存在且不为空

    我安装了Netbeans 因为我正在读这本书 Java in 21 days 我在编程领域完全是个新手 当我尝试在 Netbeans 中打开一个新项目时 出现错误 项目文件夹已存在且不为空 删除 nbproject 文件夹并重新启动 IDE
  • 如何让用户重新排序 UITableView 中的部分

    我正在开发一个包含股票的应用程序 按投资组合排列 所以这很适合表格视图 我正在研究编辑交互 它足够简单 允许用户添加或删除股票 将它们拖动到一个投资组合或另一个投资组合中 但我无法优雅地做的一件事是让用户将一个投资组合拖动到另一个投资组合的
  • 字符串损坏或 preg_match 错误?

    NO BREAK SPACE 和许多其他 UTF 8 符号需要 2 个字节来表示 http www fileformat info info unicode char a0 index htm 因此 在假定的 UTF8 字符串上下文中 非