当前位置: 首页 > 面试题库 >

正则表达式检测无效的UTF-8字符串

方轩昂
2023-03-14
问题内容

在PHP中,我们可以mb_check_encoding()用来确定字符串是否为有效的UTF-8。但这不是可移植的解决方案,因为它需要编译并启用mbstring扩展名。此外,它不会告诉我们
哪个 字符无效。

是否存在可以匹配给定字符串中无效的UTF-8字节的正则表达式(或其他100%可移植的其他方法)。这样,可以在需要时替换那些字节(保留二进制信息,例如在构建包含二进制数据的测试输出xml文件时)。因此,将字符转换为UTF-8会丢失信息。因此,我们可能要转换:

"foo" . chr(128) . chr(255)

进入

"foo<128><255>"

因此,仅“检测”该字符串不够好,我们就需要能够检测到哪些字符无效。


问题答案:

您可以使用此PCRE正则表达式来检查字符串中的有效UTF-8。如果正则表达式匹配,则该字符串包含无效的字节序列。它是100%可移植的,因为它不依赖于PCRE_UTF8进行编译。

$regex = '/(
    [\xC0-\xC1] # Invalid UTF-8 Bytes
    | [\xF5-\xFF] # Invalid UTF-8 Bytes
    | \xE0[\x80-\x9F] # Overlong encoding of prior code point
    | \xF0[\x80-\x8F] # Overlong encoding of prior code point
    | [\xC2-\xDF](?![\x80-\xBF]) # Invalid UTF-8 Sequence Start
    | [\xE0-\xEF](?![\x80-\xBF]{2}) # Invalid UTF-8 Sequence Start
    | [\xF0-\xF4](?![\x80-\xBF]{3}) # Invalid UTF-8 Sequence Start
    | (?<=[\x00-\x7F\xF5-\xFF])[\x80-\xBF] # Invalid UTF-8 Sequence Middle
    | (?<![\xC2-\xDF]|[\xE0-\xEF]|[\xE0-\xEF][\x80-\xBF]|[\xF0-\xF4]|[\xF0-\xF4][\x80-\xBF]|[\xF0-\xF4][\x80-\xBF]{2})[\x80-\xBF] # Overlong Sequence
    | (?<=[\xE0-\xEF])[\x80-\xBF](?![\x80-\xBF]) # Short 3 byte sequence
    | (?<=[\xF0-\xF4])[\x80-\xBF](?![\x80-\xBF]{2}) # Short 4 byte sequence
    | (?<=[\xF0-\xF4][\x80-\xBF])[\x80-\xBF](?![\x80-\xBF]) # Short 4 byte sequence (2)
)/x';

我们可以通过创建一些文本变体来对其进行测试:

// Overlong encoding of code point 0
$text = chr(0xC0) . chr(0x80);
var_dump(preg_match($regex, $text)); // int(1)
// Overlong encoding of 5 byte encoding
$text = chr(0xF8) . chr(0x80) . chr(0x80) . chr(0x80) . chr(0x80);
var_dump(preg_match($regex, $text)); // int(1)
// Overlong encoding of 6 byte encoding
$text = chr(0xFC) . chr(0x80) . chr(0x80) . chr(0x80) . chr(0x80) . chr(0x80);        
var_dump(preg_match($regex, $text)); // int(1)
// High code-point without trailing characters
$text = chr(0xD0) . chr(0x01);
var_dump(preg_match($regex, $text)); // int(1)

等等…

实际上,由于此匹配无效字节,因此可以在preg_replace中使用它替换掉它们:

preg_replace($regex, '', $text); // Remove all invalid UTF-8 code-points


 类似资料:
  • 问题内容: 在JavaScript中: 正确地给我: 当我使用utf-8字符时: 在字边界运营商似乎没有工作时: 这个问题有方法解决吗? 问题答案: 仅当一个单词字符之前或之后没有另一个单词字符(因此等于和)时,单词边界声明才匹配。并且定义为。因此与希腊字符不匹配。因此,您不能在这种情况下使用。 相反,您可以使用以下方法:

  • 这是应该符合以下条件的正则表达式 应仅以字母和数字开头,包含字母和数字,点和连字符不应以连字符结尾 它适用于所有条件,但当我尝试使用三个字符时,如 在四个字符验证正常工作后,我是否遗漏了什么

  • 下面是我正在使用的正则表达式的最新版本,它抛出了错误“Invalid regular expression” XSD:正则表达式在位置4验证失败:当前选项设置不支持此表达式。 我在xsd文件中得到了这个异常,我正在message broker(IIB)中开发这个xsd。有谁能帮我解决这个问题吗?

  • 问题内容: 我正在寻找Java代码来检查字符串是否为有效的XML。 问题答案: 用正则表达式验证XML是不可能的。XML不是常规语言。 使用XML解析器尝试将字符串解析为XML,或者对照模式(例如DTD或XSD文件)验证XML文档。

  • 我有一个包含数千行的文本文件。这里有一个例子 我试图提取'nt60'、'nt50'末尾的字符串。 问题是会包含行尾字符() 我想使用正则表达式搜索来匹配从 (') 开始的字符串,但我不知道我应该用什么来匹配 。 有人能帮忙吗?

  • 主要内容:实例下表包含了元字符的完整列表以及它们在正则表达式上下文中的行为: 字符 描述 \ 将下一个字符标记为一个特殊字符、或一个原义字符、或一个 向后引用、或一个八进制转义符。例如,'n' 匹配字符 "n"。'\n' 匹配一个换行符。序列 '\\' 匹配 "\" 而 "\(" 则匹配 "("。 ^ 匹配输入字符串的开始位置。如果设置了 RegExp 对象的 Multiline 属性,^ 也匹配 '\n' 或