这是我使用的模式:
\n"\\w+|[^\\w\\s]+"\nRun Code Online (Sandbox Code Playgroud)\n当我匹配字符串“abc.efg”和“\xe6\x88\xa6\xe5\xa0\xb4\xe3\x81\xae\xe3\x83\xb4\xe3\x82\xa1\xe3\x83\xab\xe3\ x82\xad\xe3\x83\xa5\xe3\x83\xaa\xe3\x82\xa23" 在https://regexr.com/中使用 PCRE ,\nit 给我这样的结果:
\n"abc" "." "efg" => 3 parts\n\n"\xe6\x88\xa6\xe5\xa0\xb4\xe3\x81\xae\xe3\x83\xb4\xe3\x82\xa1\xe3\x83\xab\xe3\x82\xad\xe3\x83\xa5\xe3\x83\xaa\xe3\x82\xa2" "3" => 2 parts\nRun Code Online (Sandbox Code Playgroud)\n看起来是对的。
\n但是当我像这样使用 icu 时:
\n //std::string ldata = "abc.efg";\n std::string ldata = "\xe6\x88\xa6\xe5\xa0\xb4\xe3\x81\xae\xe3\x83\xb4\xe3\x82\xa1\xe3\x83\xab\xe3\x82\xad\xe3\x83\xa5\xe3\x83\xaa\xe3\x82\xa23";\n std::string m_regex = "\\\\w+|[^\\\\w\\\\s]+";\n UErrorCode status = U_ZERO_ERROR;\n icu::RegexMatcher matcher(m_regex.c_str(), 0, status);\n icu::StringPiece data((char*)ldata.data(), ldata.length());\n icu::UnicodeString input = icu::UnicodeString::fromUTF8(data);\n matcher.reset(input);\n \n \n int count = 0;\n while (matcher.find(status) && U_SUCCESS(status))\n {\n auto start_index = matcher.start(status);\n auto end_index = matcher.end(status);\n count++; \n }\nRun Code Online (Sandbox Code Playgroud)\n输入字符串“abc.efg”给我:
\n"abc" "." "efg" => 3 parts\nRun Code Online (Sandbox Code Playgroud)\n但输入字符串“\xe6\x88\xa6\xe5\xa0\xb4\xe3\x81\xae\xe3\x83\xb4\xe3\x82\xa1\xe3\x83\xab\xe3\x82\xad\xe3\ x83\xa5\xe3\x83\xaa\xe3\x82\xa23”给我:
\n"\xe6\x88\xa6\xe5\xa0\xb4\xe3\x81\xae\xe3\x83\xb4\xe3\x82\xa1\xe3\x83\xab\xe3\x82\xad\xe3\x83\xa5\xe3\x83\xaa\xe3\x82\xa23" => 1 part\nRun Code Online (Sandbox Code Playgroud)\n当我像这样使用 Rust 时:
\nimpl Pattern for &Regex {\n fn find_matches(&self, inside: &str) -> Result<Vec<(Offsets, bool)>> {\n if inside.is_empty() {\n return Ok(vec![((0, 0), false)]);\n }\n\n let mut prev = 0;\n let mut splits = Vec::with_capacity(inside.len());\n for m in self.find_iter(inside) {\n if prev != m.start() {\n splits.push(((prev, m.start()), false));\n }\n splits.push(((m.start(), m.end()), true));\n prev = m.end();\n }\n if prev != inside.len() {\n splits.push(((prev, inside.len()), false))\n }\n Ok(splits)\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n输入字符串“abc.efg”给我:
\n"abc" "." "efg" => 3 parts\nRun Code Online (Sandbox Code Playgroud)\n但输入字符串“\xe6\x88\xa6\xe5\xa0\xb4\xe3\x81\xae\xe3\x83\xb4\xe3\x82\xa1\xe3\x83\xab\xe3\x82\xad\xe3\ x83\xa5\xe3\x83\xaa\xe3\x82\xa23”给我:
\n"\xe6\x88\xa6\xe5\xa0\xb4\xe3\x81\xae\xe3\x83\xb4\xe3\x82\xa1\xe3\x83\xab\xe3\x82\xad\xe3\x83\xa5\xe3\x83\xaa\xe3\x82\xa23" => 1 part\nRun Code Online (Sandbox Code Playgroud)\n为什么 ICU 和 Rust 匹配 "\xe6\x88\xa6\xe5\xa0\xb4\xe3\x81\xae\xe3\x83\xb4\xe3\x82\xa1\xe3\x83\xab\xe3\x82\xad\xe3 \x83\xa5\xe3\x83\xaa\xe3\x82\xa23" 给出与 PCRE 不同的结果(https://regexr.com/)
\n看起来“\xe6\x88\xa6\xe5\xa0\xb4\xe3\x81\xae\xe3\x83\xb4\xe3\x82\xa1\xe3\x83\xab\xe3\x82\xad\xe3\x83 \xa5\xe3\x83\xaa\xe3\x82\xa23" 应匹配为 2 部分。
\nICU 和正则表达式默认使用 unicode 语义,这意味着\\w它们使用“单词字符”的 unicode 感知定义。
[\\p{Alphabetic}\\p{M}\\p{Nd}\\p{Pc}\\p{Join_Control}]\nRun Code Online (Sandbox Code Playgroud)\n对于 ICU 来说
\n[\\p{Alphabetic}\\p{Mark}\\p{Decimal_Number}\\p{Connector_Punctuation}\\u200c\\u200d]\nRun Code Online (Sandbox Code Playgroud)\n\nLowercase + Uppercase + Lt + Lm + Lo + Nl + Other_Alphabetic\nRun Code Online (Sandbox Code Playgroud)\nCJK 字符通常被分类为“字母、其他”(Lo),因此属于\\wunicode 感知分类的一部分。显然,“3”也是如此。因此只有一个组,因为它们都匹配得\\w+很好。
PCRE 默认情况下不使用 unicode 语义1因此它不处理 "\xe6\x88\xa6\xe5\xa0\xb4\xe3\x81\xae\xe3\x83\xb4\xe3\x82\xa1\xe3\x83\ xab\xe3\x82\xad\xe3\x83\xa5\xe3\x83\xaa\xe3\x82\xa2" 作为字母。
\nregex 支持非 unicode 匹配(使用基于字节的引擎或标志(?-u:)),我不知道 ICU 是否支持,尽管我相当怀疑它,因为它完全违背了这一点。
如果您想要特定的 ASCII 匹配,只需提出要求即可。
\n还是您误解了其中的\\w内容并认为它不包含数字?因此 PCRE 匹配“\xe6\x88\xa6\xe5\xa0\xb4\xe3\x81\xae\xe3\x83\xb4\xe3\x82\xa1\xe3\x83\xab\xe3\x82\xad\xe3 \x83\xa5\xe3\x83\xaa\xe3\x82\xa2”到\\w+和“3”到[^\\w\\s]+?因为它的作用恰恰相反。
1:PCRE2_UCP允许启用 unicode 语义