Php 分解有关大写或数字字符的UTF8字符串
例如,我可以拆分包含大写字母的字符串,如下所示:Php 分解有关大写或数字字符的UTF8字符串,php,regex,string,utf-8,preg-replace,Php,Regex,String,Utf 8,Preg Replace,例如,我可以拆分包含大写字母的字符串,如下所示: function splitAtUpperCase($string){ return preg_replace('/([a-z0-9])?([A-Z])/','$1 $2',$string); } $string = 'setIfUnmodifiedSince'; echo splitAtUpperCase($string); 输出为“自后未修改时设置” 但我需要一些修改: 当这些字符以字符串形式存在时,该代码段不会处理这些情况:Ö
function splitAtUpperCase($string){
return preg_replace('/([a-z0-9])?([A-Z])/','$1 $2',$string);
}
$string = 'setIfUnmodifiedSince';
echo splitAtUpperCase($string);
输出为“自后未修改时设置”
但我需要一些修改:
- 当这些字符以字符串形式存在时,该代码段不会处理这些情况:
。我不想音译这些字符。然后我就失去了这个词的意思。我需要使用一些UTF字符。该代码将“Here ch on Then”改为“Here ch on Then”ÖĞŞ࢜
- 我也不想拆分大写缩写。如果单词是“我知道你会尽快来这里”,我需要将它转换为“我知道你会尽快来这里”
- 如果所有字母都是大写,则不要爆炸。比如“DONTCOMEHERE”
- 也分解数值。“2013年底前”至“2013年底前”
- 如果第一个字符是散列键(#),则分解
str\u replace
操作。我寻找一个简短的解决方案,它不会让循环检查单词。如果可能的话,最好将其作为preg\u replace
等
编辑:任何人都可以通过更改此PHP小提琴中的convert
函数来尝试他的解决方案:/([:lower:][:digit:][])?([:upper:][]+)/u
应该这样做
这里/u
用于Unicode字符。而([[:upper:][]+)
用于大写字母的顺序
注意。字母的大小写取决于您使用的字符集 一些注意事项:
- 用于搜索大写和小写字母(甚至是标题大小写字母,f.ex.
)LjNjDz
&明天来这里
在使用一些字典查找确切的单词之前,一种方法无法使用 因为如果你想把我知道
翻译成明天来这里
,明天来这里
将是我知道
(甚至是IK现在
) 如果你想把IK现在
翻译成我知道
,我知道
将是明天来这里
明天来
\p{Lu}表示大写
和\p{Li}表示小写
因此,您的用法如下所示:
/([\p{Ll}0-9])?([\p{Lu}])/
嗯,但我仍然认为这不是一个好的解决方案。(测试驱动设计中为数不多的缺陷之一)
我采取了稍微不同的方法。我没有试图写一个正则表达式来表示单词之间的位置应该是什么样子,而是写了一个正则表达式来查找所有明显是单词的东西,然后就内爆了
function convert($keyword) {
$wResult = preg_match_all('/(^I|[[:upper:]]{2,}|[[:upper:]][[:lower:]]*|[[:lower:]]+|\d+|#)/u', $keyword, $matches);
return implode(' ',$matches[0]);
}
正如你所看到的,这是我认定的一个词:
^I A capital I at the beginning of the string. Break point: Icons.
[[:upper:]]{2,} Consecutive capitals. Break Point: WellIKnowThat
[[:upper:]][[:lower:]]* A single Capital followed by some lower case letters
[[:lower:]]+ A string of lower case letters
\d+ A string of digits
# A literal #
它并不完美-仍然有许多断点。你可以继续完善这些词的定义,但坦率地说,总会有一个你抓不到的边缘案例。然后慢慢地扩展这个正则表达式,直到它完全无法管理为止。你可以尝试使用字典,但最终也会失败。你怎么处理“旋风”?还是“伊坦”?那是“IT an”还是“I Tan”?举个例子?这是在我试图抓住我的一些错误之后。它变得如此巨大,而想出一条断开的线仍然是微不足道的。这个函数是关于度的-花多少时间来教你的算法世界上所有语言的有趣之处
编辑:在做了一些工作之后,决定我可以被分离出来作为它自己的单词,当且仅当它后面紧跟着一个大写字母和一个小写字母
我还添加了一些新的测试用例:
convert("Icons") = "Icons"
convert("WellIKnowThat") == "Well I Know That"
convert("ITan") == "I Tan"
convert("whirlwind") == "whirlwind"
我想这和今天一样好。按优先顺序排列的最后一组“单词定义”是:
I(?=[:Upper:][:lower:]])
[[:upper:]{2,}
[[:upper:][[:Lower:]*
[:lower:]+
\d+
#
我添加了另一个单词定义,一个测试用例。新的单词定义与
I
的规则匹配,但与A
匹配,后者是英语中唯一的一个字母单词。如何正则表达式将知道I
在IKnow
中是不同的单词?这是不可能的。与Asphere相同。如果随后有两个大写字母和一个小写字母,则将其拆分,如果有两个以上大写字母,则存在缩写,因此,在没有得到下一个单词的第一个字母的情况下拆分它。那么你想将JScript
拆分为J Script
?顺便问一下,除了另一个问题中的代码片段之外,你做了什么?什么逻辑可以将明天这里拆分为明天这里
和IKnow
拆分为我知道的而不是IK现在
?谢谢你的回答,看起来很好。我不打算使用非字母数字字符。我没有选择使用字典。所以也许可以忽略“IKnowThat”。如果散列(#)是第一个字符,就不可能拆分吗?否则我将添加$wResult=str_替换(“#“,”#“,$wResult)代码>到结果字符串
convert("Icons") = "Icons"
convert("WellIKnowThat") == "Well I Know That"
convert("ITan") == "I Tan"
convert("whirlwind") == "whirlwind"