preg_split对特殊字符不区分大小写。

4

我正在编写一个脚本,该脚本将餐厅菜单的字符串按大写字母分割。不幸的是,在捷克语中,一些单词以带有变音符号的特殊字符开头。通过“常规”大写字母拆分菜肴效果很好,但我的正则表达式对于某些特殊字符是不区分大小写的,导致它用例如Š来拆分字符串时应该只按Š拆分。奇怪的是,一些特殊字符工作得非常好,到目前为止唯一有问题的字母是š/Š。 请问有人可以帮忙吗?

$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
)

(don't mind the first empty row) Thank you!


1
你应该使用/u修饰符。尝试$dishes = preg_split('/(?=[ABCDEFGHIJKLMNOPQRSTUVWXYZÁČĎÉĚÍŇÓŘŠŤÚŮÝŽĹÔÄËÏÖÜŸ])/u', $dishes); - Wiktor Stribiżew
如果您使用'\u0160'代替'Š',它是否有效? - mnme
使其通用:preg_split('/(?=\p{Lu})/u', $dishes); - Lucas Trzesniewski
1
如果目标是仅匹配特定的字母,则\p{Lu}可能会过度匹配。 - Wiktor Stribiżew
我想让它通用化,但不幸的是你的代码(Lucas)根本没有将其分割。添加/u也没有帮助。 - Jan Hůda
2个回答

1
当你在PHP的正则表达式中处理Unicode输入数据时,请记得使用/u正则表达式修饰符:

preg

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

请注意,您需要使用UTF8编码保存PHP文件!
这将使正则表达式引擎将输入视为Unicode字符串,并正确处理包含非ASCII字符的正则表达式模式。
如果您需要匹配任何Unicode大写字母(如LucasTrzesniewski在上面的评论中提到的),可以使用\p{Lu} Unicode类别类:
$dishes = preg_split('/(?=\p{Lu})/u', $dishes);

请注意,有时您不必使用/u修饰符。请参见丹尼尔·克莱因的评论

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

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

还有来自hfuecks的更多警告:

关于使用/u模式修饰符时UTF-8字符串的有效性,需要注意以下几点:
1.如果模式本身包含无效的UTF-8字符,则会出现错误(如上文所述,“自PHP 4.3.5以来,检查模式的UTF-8有效性”)。
2.当主题字符串包含无效的UTF-8序列/代码点时,preg_*函数基本上会“悄悄死亡”,没有任何匹配但没有指示字符串无效UTF-8。
3.PCRE将五个和六个八位字节的UTF-8字符序列视为有效的(在模式和主题字符串中),但这些在Unicode中不受支持(请参见“Linux和Unix HOWTO安全编程”的第5.9节“字符编码” - 可在http://www.tldp.org/等地方找到)。
4.有一个用于测试UTF-8字符串有效性(并丢弃五/六个八位字节序列)的PHP示例算法,请访问http://hsivonen.iki.fi/php-utf8/
所以,尝试中

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

这可能取决于你想要达到的目标,对于你的情况来说可能已经足够了。

该死,我用了你(或者卢卡斯)的代码,它根本没有分割,但是我去掉了“u”,现在看起来运行良好。谢谢! :) 现在我该怎么办?即使它只部分地解决了我的问题,我是否应该将其标记为已批准? - Jan Hůda
你说$dishes = preg_split('/(?=\p{Lu})/', $dishes);对你有用吗?你是在将UTF8字符串分解成字节吗? - Wiktor Stribiżew
我添加了一些关于 u 标志用法的信息,希望能有所帮助。 - Wiktor Stribiżew
我不确定,通常我会遇到一些特殊符号的问题。这个目的只是为了在数据库中填充大量的数据,所以它只涉及字符串操作。正如你所看到的,我并不是一个专家,尤其是当涉及到正则表达式时 :) - Jan Hůda
好的,对不起,我的错误,毕竟它并没有起作用。当我使用$dishes = preg_split('/(?=\p{Lu})/u', $dishes);时,它根本没有分割,而当我使用$dishes = preg_split('/(?=\p{Lu})/', $dishes);时,它不会按任何特殊字符(Š、Ž、Č等)进行分割。你所说的将UTF8字符串分解成字节是什么意思? - Jan Hůda

-1

我把 PHP 文件保存为 UTF-8,但应该保存为 Windows-1250。将其保存为 Windows-1250 解决了问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接