PHP pre_match

sec

PHP pre_match

PHP 的 pre_match 函数正则匹配的时候出错,研究了好几个小时。

问题如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$str = array(
'剩余',
'距离',
"套餐",
'香港x2',
'香港',
'中国',
'北京',
'俄罗斯远东',
'USA',
'达拉斯'
);

$pre = "/^[剩|距|套]/u";

foreach ($str as $i) {
if (preg_match($pre, $i)) {
echo "Yes $i \r\n";
} else {
echo "No $i \r\n";
}
}

运行的结果是:

1
2
3
4
5
6
7
8
9
10
Yes 剩余 
Yes 距离
Yes 套餐
No 香港x2
No 香港
No 中国
Yes 北京
No 俄罗斯远东
No USA
Yes 达拉斯

出现了两个错误匹配

正确的代码

正确的表达式应该

1
$pre = "/^[剩|距|套]/u";

加上 u 表示匹配 unicode 中文字符

原因分析

我们用 winhex 查看 “剩距套北达” 这五个字的 16 进制编码

E5 89 A9 E8 B7 9D E5 A5 97 E5 8C 97 E8 BE BE

我们发现他们的开头都是 E5 和 E8,猜测,在处理时,吧字符串当做 asiic 处理的,所以,我们在匹配字符串中删去开头为 E8 的 ”距“ 字,此时,”达拉斯“ 应该不匹配,”北京“继续匹配,验证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$str = array(
'剩余',
'距离',
"套餐",
'香港x2',
'香港',
'中国',
'北京',
'俄罗斯远东',
'USA',
'达拉斯'
);

$pre = "/^[剩|套]/";

foreach ($str as $i) {
if (preg_match($pre, $i)) {
echo "Yes $i \r\n";
} else {
echo "No $i \r\n";
}
}
1
2
3
4
5
6
7
8
9
10
Yes 剩余 
No 距离
Yes 套餐
No 香港x2
No 香港
No 中国
Yes 北京
No 俄罗斯远东
No USA
No 达拉斯

….. 这个小问题,搞了好几个小时,累死了

Author: 哒琳

Permalink: http://blog.jieis.cn/2022/a0f0042d-36ff-4860-9c72-938e2874fc57.html

Comments