1

我正在尝试使用正则表达式来清理/格式化某些输入,以进行混合的拉丁语/表意文字(中文/日文/韩文)全文搜索。

我在一个我再也找不到的论坛上找到了一个有人尝试清理拉丁/亚洲语言字符串的旧示例(完全归功于此代码的原作者)。

我无法完全理解函数的正则表达式部分,特别是为什么它似乎对数字 0、2 和 3 的处理方式与其他基于拉丁文的数字 1,4-9 不同(基本上它处理数字 0、 4-9 正确,但查询中的数字 0,2-3 被视为亚洲字符)。

例如。我正在尝试清理以下字符串:
“hello 1234567890 蓄积した abc123def”

它会变成:
“hello 1 456789 abc1 def 2 3 0 蓄积した 2 3”

此净化字符串的正确输出应为:
“hello 1234567890 蓄积した abc123def”

如您所见,它正确地隔开亚洲字符,但数字 0、2、3 的处理方式与所有其他数字不同。关于为什么正则表达式以不同方式处理这些数字 0,2 和 3 的任何帮助将是一个很大的帮助(或者如果您知道实现类似结果的更好方法)!谢谢

我已经包含了下面的功能

函数准备字符串($str){
$str = mb_strtolower(trim(preg_replace('#[^\p{L}\p{Nd}\.]+#u', ' ', $str)));

return trim(preg_replace('#\s\s+#u', ' ', preg_replace('#([^\12544-\65519])#u', ' ', $str) . ' ' . implode(' ' , preg_split('#([\12544-\65519\s])?#u', $str, -1, PREG_SPLIT_NO_EMPTY))));
}

更新:为清楚起见提供上下文

我正在创作一个将在中国推出的网站。该网站将具有搜索功能,我正在尝试为搜索查询输入编写解析器。

与英语使用“ ”作为句子中单词之间的分隔符不同,中文不使用单词之间的空格。因此,我必须通过拆分每个汉字并在数据库中单独搜索每个字符来重新格式化搜索查询。中国用户还将使用拉丁/英文字符来表示品牌名称等他们可以与他们的中文字符混合在一起的东西(例如,Ivy新闻铺)。

我想做的是将所有英文单词与汉字分开,并用空格分隔每个汉字。

搜索查询可能如下所示:Ivy 铺</p>

我想解析它,使它看起来像这样:Ivy 牛仔铺</p>

4

3 回答 3

1

问题似乎与正则表达式有关[^\12544-\65519]。看起来它应该是由两个五位八进制转义定义的范围,但它不是那样工作的。实际分解是这样的:

\125 => octal escape for 'U'
4    => '4'
4    => '4'
-
\655 => octal escape for... (something)
1    => '1'
9    => '9'

这实际上与以下内容相同:

[^14-\655]

范围顶部的含义尚不清楚,但字符类匹配除“ \6551”、“4”或代码点高于“4”的任何 ASCII 字符(包括“9”和'你')。不过这并不重要;重要的一点是八进制转义最多可以包含三位数字,这使得它们不适合您的需要。我建议您改用 PHP 的\x{nnn}十六进制表示法。

于 2009-07-05T01:08:31.433 回答
1

我没有准备好使用 PHP 或中文,所以我不能给你一个明确的答案,但这至少应该可以帮助你完善这个问题。在我看来,这基本上是一个四步过程:

  • 去掉标点符号等不受欢迎的字符,用空格替换它们

  • 规范化空格:去掉前导和尾随空格,并将两个或多个空格的运行折叠到一个空格

  • 规范化大小写:将任何大写字母替换为对应的小写字母

  • 如果一个汉字紧挨着另一个非空白字符,则用空格分隔这两个字符

对于前三个步骤,您发布的代码的第一行就足够了:

$str = mb_strtolower(trim(preg_replace('#[^\p{L}\p{Nd}\.]+#u', ' ', $str)));

对于最后一步,我建议环顾四周:

$str = preg_replace(
    '#(?<=\S)(?=\p{Chinese})|(?<=\p{Chinese})(?=\S)#u',
    ' ', $str);

那应该在下一个字符是中文并且前一个字符不是空格的任何位置插入一个空格,或者前一个字符是中文并且下一个字符不是空格。

于 2009-07-07T21:55:46.963 回答
0

经过进一步的研究和 Alan 的评论的帮助,我能够找到正确的正则表达式组合来实现查询解析功能,用于分离我很满意的 lating 和 ideographic (chinese/japanese) 字符:

函数准备字符串($str){
    $str = mb_strtolower(trim(preg_replace('#[^\p{L}\p{Nd}]+#u', ' ', $str)));
    return trim(preg_replace('#\s\s+#u', '', preg_replace('#\p{Han}#u', ' ', $str) . ' ' . implode(' ', preg_split('# \P{Han}?#u', $str, -1, PREG_SPLIT_NO_EMPTY))));
}

$query = "米娜娜娜娜日系时尚╭☆ 旅行渡假风格【A6402】korea Mi 风景馆-飞鼠棉

回声准备字符串($查询);//"mi nana a6402 korea 米娜日系时尚馆旅行渡假风格拼接条纹口袋飞鼠棉"

免责声明:我看不懂普通话,上面的字符串是从中文网站复制的。如果它说任何冒犯,请告诉我,我会删除它。

于 2009-07-07T23:51:16.760 回答