【问题标题】:preg_split is case insensitive with special characterspreg_split 对特殊字符不区分大小写
【发布时间】:2015-09-29 11:45:10
【问题描述】:

我正在编写一个用大写字母分割字符串(餐厅菜单)的脚本。不幸的是,在捷克语中,一些单词以带有变音符号的特殊字符开头。用“普通”大写字母分割菜肴效果很好,但我的正则表达式对某些特殊字符不区分大小写,它用例如分割字符串。 š 什么时候应该只用 Š 拆分它。奇怪的是,一些特殊字符工作得很好,到目前为止唯一有问题的字母是š/Š。 谁能帮帮我?

$dishes = preg_split('/(?=[ABCDEFGHIJKLMNOPQRSTUVWXYZÁČĎÉĚÍŇÓŘŠŤÚŮÝŽĹÔÄËÏÖÜŸ])/', $dishes); 
print_r($dishes);

以上代码返回

Array
(
    [0] =>
    [1] => Vepřová plec na paprice s těstovinami
    [2] => Domácí sekaná s bramborovou ka
    [3] => ší
    [4] => Těstoviny s rajským jablkem, olivami a žervé
    [5] => Domácí sekaná s e svíčkovou omáčkou
    [6] => Uzená kýta s čočkou na kyselo a vejcem 
    [7] => Vepřové  nudličky se zeleninou a rýží
    [8] => Pečená vepřová plec na medu a pivu s bramborami
    [9] => Plzeňský gulá
    [10] => š
    [11] => Hovězí zadní se svíčkovou omáčkou, citron, brusinky, 
    [12] => šlehačka
)

(不要介意第一个空行) 谢谢!

【问题讨论】:

  • 你应该使用/u修饰符。试试$dishes = preg_split('/(?=[ABCDEFGHIJKLMNOPQRSTUVWXYZÁČĎÉĚÍŇÓŘŠŤÚŮÝŽĹÔÄËÏÖÜŸ])/u', $dishes);
  • 如果你使用 '\u0160' 而不是 'Š' 是否有效?
  • 使其通用:preg_split('/(?=\p{Lu})/u', $dishes);
  • @LucasTrzesniewski:如果目标是只匹配特定的字母,那么\p{Lu} 可能会过度匹配。
  • 我想让它通用,不幸的是你的代码 (Lucas) 根本没有拆分它。添加 /u 也无济于事

标签: php regex string


【解决方案1】:

当您在 PHP preg 函数中使用正则表达式处理 Unicode 输入数据时,请记住使用 /u 正则表达式修饰符:

$dishes = preg_split('/(?=[ABCDEFGHIJKLMNOPQRSTUVWXYZÁČĎÉĚÍŇÓŘŠŤÚŮÝŽĹÔÄËÏÖÜŸ])/u', $dishes);

注意,PHP文件需要用UTF8编码保存!

这将使正则表达式引擎将输入视为 Unicode 字符串,并正确处理包含非 ASCII 字符的正则表达式模式。

如果您需要匹配 任何 Unicode 大写字母(正如 LucasTrzesniewski 在上面的评论中提到的),您可以使用 \p{Lu} Unicode 类别类:

$dishes = preg_split('/(?=\p{Lu})/u', $dishes);

请注意,有时您不必使用/u 修饰符。见Daniel Klein's comment

但这不是必需的,因为您可能需要将 utf-8 序列分解为单个字节。不过,大多数情况下,如果您使用的是 utf-8 字符串,则应该使用 'u' 修饰符。

如果主题不包含任何 utf-8 序列(即仅 0x00-0x7F 范围内的字符)但模式包含,据我所知,设置 'u' 修饰符对结果。

还有来自hfuecks的更多警告:

关于使用 /u 模式修饰符时 UTF-8 字符串的有效性,需要注意的一些事项;

  1. 如果模式本身包含无效的 UTF-8 字符,则会出现错误(如上面的文档中所述 - “UTF-8 有效性的 自 PHP 4.3.5 起检查模式"
  2. 当主题字符串包含无效的 UTF-8 序列/代码点时,它基本上会导致 preg_* 功能,其中没有任何匹配但没有迹象表明 字符串是无效的 UTF-8
  3. PCRE 将五个和六个八位字节的 UTF-8 字符序列视为有效(在模式和主题字符串中),但不支持这些 在 Unicode 中(参见“安全”的第 5.9 节“字符编码” Programming for Linux and Unix HOWTO”——可以在以下位置找到 http://www.tldp.org/等地)
  4. 对于 PHP 中测试 UTF-8 字符串有效性(并丢弃五个/六个八位字节序列)的示例算法,请访问: http://hsivonen.iki.fi/php-utf8/

所以,试试

$dishes = preg_split('/(?=\p{Lu})/u', $dishes);

根据您要达到的目标,对于您的情况可能就足够了。

【讨论】:

  • 该死,我使用了你的(分别是卢卡斯的代码)它根本没有分裂,但我删除了“u”,它似乎工作正常。谢谢! :) 我现在该怎么办,我是否将其标记为已批准,即使它仅部分解决了我的问题?
  • 你说$dishes = preg_split('/(?=\p{Lu})/', $dishes); 适合你吗?您是否将 UTF8 字符串分解为字节?
  • 我添加了更多关于u 标志用法的信息,希望对您有所帮助。
  • 我不确定,一般来说我在使用特殊标志时遇到了一些问题。这样做的目的只是为了填充数据库中的大量菜肴,所以它只是使用字符串,正如你所知,我不是专家,尤其是在涉及正则表达式时:)
  • 好吧,对不起,我的错误,毕竟它不起作用,当我使用$dishes = preg_split('/(?=\p{Lu})/u', $dishes);时,它根本不会分裂,当我使用$dishes = preg_split('/(?=\p{Lu})/', $dishes);时它不会被任何特殊分裂字符(Š、Ž、Č、...)。将 UTF8 字符串分成几段是什么意思?
【解决方案2】:

当我应该将 PHP 文件保存为 Windows-1250 时,我将其保存为 UTF-8。将其保存为 Windows-1250 解决了这个问题。

【讨论】:

    猜你喜欢
    • 2022-12-18
    • 2018-03-02
    • 2013-07-07
    • 1970-01-01
    • 2020-02-18
    • 2015-06-07
    • 1970-01-01
    • 1970-01-01
    • 2015-07-07
    相关资源
    最近更新 更多