我正在考虑PHP中的一个特殊的regexp问题,但我找不到解决方案。 我尝试将一些文本拆分成术语以获得简单的单词,数字和网址。
所以我决定拆分每个非字母数字字符(\ w)。
要使用不同的语言,我会使用\ w和其他字母,例如ÄäéèÈ等。
示例:
20,000 15.20 This is at Text. Right?!
www.google.com Jean Béraud
到目前为止,我使用以下正则表达式来分割文本:
[^\w(äÄüÜöÖßèé)]
在80%的案例中效果很好,但将20,000分为20和000也将www.google.com分成www google com
所以我试着将这些数字保持在一起,但仍然分为点数,例如Text.
以获得Text
要匹配15.20,以下工作:(\d+\.\d+)
,但如何将否定与其他正则表达式字符串组合?以下操作无效:(\d+\.\d+)|[^\w(äÄüÜöÖßèé)]
?
并且:我如何处理网址?
答案 0 :(得分:2)
这样的东西?
$result = preg_split('/\W*\s+/', $string, NULL, PREG_SPLIT_NO_EMPTY);
Demo,结果:
array(10) {
[0]=>
string(6) "20,000"
[1]=>
string(5) "15.20"
[2]=>
string(4) "This"
[3]=>
string(2) "is"
[4]=>
string(2) "at"
[5]=>
string(4) "Text"
[6]=>
string(5) "Right"
[7]=>
string(14) "www.google.com"
[8]=>
string(4) "Jean"
[9]=>
string(7) "Béraud"
}
问:为什么\w
在我的示例中匹配é
?
答:这是基于使用PCRE库的系统的本地,来自PHP Manual:
“单词”字符是任何字母或数字或下划线字符,即任何可以成为Perl“单词”一部分的字符。字母和数字的定义由PCRE的字符表控制,如果发生特定于语言环境的匹配,则可能会有所不同。例如,在“fr”(法语)语言环境中,一些大于128的字符代码用于重音字母,并且这些字符代码由\ w匹配。
或者,将正则表达式指定为使用UTF-8可能会有所帮助:
$result = preg_split('/\W*\s+/u', $string, NULL, PREG_SPLIT_NO_EMPTY);
确保$string
采用UTF-8编码。由于UTF-8是国际的,因此可能不需要考虑特定的区域设置。试一试。
答案 1 :(得分:1)
根据@hakre的回答和你的例子,我相信你应该用这种方式组合这两个表达式:
$result = preg_split('/[^\wäÄüÜöÖßèé]*\s+[^\wäÄüÜöÖßèé]*/', $string, NULL, PREG_SPLIT_NO_EMPTY);
您的原始表达式已成功匹配相应的字符([^\w(äÄüÜöÖßèé)]
部分)。
来自@hakre的表达式补充说,这些字符中可能有任意一个字符(甚至没有字符),并且还应该跟一个或多个空格实例(\s+
部分)。
当你将这两个想法结合起来时,你会得到[^\wäÄüÜöÖßèé]*\s+[^\wäÄüÜöÖßèé]*
,这基本上转化为
此字符类中没有的任意数量的字符,后跟至少一个空格字符,然后可能后跟任何不在此字符类中的字符
或
之前或之后的一个或多个空白字符,以及不在此字符类中的任意数量的字符
作为测试,我使用了这个文本示例(我假设你想匹配法语字符):
20,000 15.20 This is at Text. Right?!
www.google.com Comme son élève, où dois-je aller voir Jean Béraud?
和这个正则表达式: 的 EDITED 强>
/[^\wßàâäèéêëîïôöœùûüÿç]*(^|$|\s+)[^\wßàâäèéêëîïôöœùûüÿç]*/i
通过@hakre使用的同一网站:
http://codepad.viper-7.com/MqztVt
结束编辑
此测试显示即使单词以其中一个特殊字符开头或结尾,表达式也会分裂。我在表达式的末尾添加了/i
开关,以使匹配不区分大小写。