sakko51150 发表于 2017-4-9 12:45:51

PHP匹配UTF-8中文字符的正则表达式

  
<script type="text/javascript"><!--
google_ad_client = "pub-0241434510974184";
/* auto-http.cn 右边 ,468x60 */
google_ad_slot = "0902256228";
google_ad_width = 468;
google_ad_height = 60;
// --></script><script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript"></script>
  急着用的朋友可以先拿去用,这个正则非原创,但是经过我的修改,如有问题,请回复告知,代码是写给PHP初学者的,高手请自抠正则。

<meta http-equiv="Content-Type" Content="text/html; charset=utf-8">
<?php
$word = "中文";
if (preg_match("/^([".chr(228)."-".chr(233)."]{1}[".chr(128)."-".chr(191)."]{1}[".chr(128)."-".chr(191)."]{1}){1}/",$word) == true || preg_match("/([".chr(228)."-".chr(233)."]{1}[".chr(128)."-".chr(191)."]{1}[".chr(128)."-".chr(191)."]{1}){1}$/",$word) == true || preg_match("/([".chr(228)."-".chr(233)."]{1}[".chr(128)."-".chr(191)."]{1}[".chr(128)."-".chr(191)."]{1}){2,}/",$word) == true)
{
echo "很好,这是一个UTF-8编码的汉字";
}
else
{
echo "抱歉,这不是一个UTF-8编码的汉字";
}
?>



  先不要被上面那个稀奇古怪的代码吓到,看完这篇文章以后,你就不会觉得它了不起了:)另外,本文不会卖弄大量的关于编码的概念,如果需要额外的扩展阅读,请通过google查找,相信一定能够满足您的阅读需求。
  关于编码:
  上海的邮政编码是200000 ,上海的地理编码(经纬度)是lat:31.2356;lng:121.4728,上海的电话编码(国际区号)是:086021。类比在计算机里面,“汉”字的gb2312编码是:1011 1010 1011 1010(16进制:BABA);“汉”字的Unicode编码是 0110 1100 0100 1001(16进制:6C49);“汉”字的UTF-8编码是1110 0110 1011 0001 1000 1001 (16进制:E6B189)。所以,不同的汉字,在不同的编码方式下,表示的方法也是不一样的。
  关于unicode:
  随着全球化的到来,全球性的的沟通变得异常的普遍,在互联网的世界里,为了能够让用户方便的访问全世界不同地域,不同文字(编码)的站点,历史上先后有两个试图独立设计Unicode的组织,即国际标准化组织(ISO)和一个软件制造商的协会(unicode.org)。在1991年前后,双方都认识到世界不需要两个不兼容的字符集。于是它们开始合并双方的工作成果,并为创立一个单一编码表而协同工作。于是,真正意义上的Unicode孕育而生。
  Unicode的学名是"Universal Multiple-Octet Coded Character Set",简称为UCS。UCS可以看作是"Unicode Character Set"的缩写。简单的说Unicode是一种可以容纳全世界所有语言文字的编码方案。
  unicode编码在前面已经看到了,补充一点,有的时候还会用10进制中文字符,所以“汉”字还有可能是这个样子:27721

<script>
document.write("汉".charCodeAt());//显示27721
</script>



  关于UTF-8:
  UTF-8是unicode编码的扩展(也可以说是子集:Unicode Translation Format),由Ken Thompson于1992年创建,只要将某个字符的unicode编码一一插入相应的空位(刚好有16个空位)就可以成为一个UTF-8编码,细心的研究一下刚才给出的“汉”字的例子,你就能发现这一点。

1 1 1 0 _ _ _ _ 1 0 _ _ _ _ _ _ 1 0 _ _ _ _ _ _


  好了,我们现在已经了解了关于unicode,编码和UTF-8的相关知识(虽然并不全面),但是我们还需要一些工具:
  一个进制转换的页面(觉得麻烦的话可以google现成的):

<meta http-equiv="Content-Type" Content="text/html; charset=utf-8">
<script>
var hex = new Array("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F");
function CKparseInt(n, r) {
for (var i = 0; i < n.length; ++i)
if (n.charAt(i) >= r) {
alert("格式错");
return 0;
}
if (isNaN(M = parseInt(n, r)))
alert ("格式错");
return M;
}
function DecimaltoAnother(A, radix) {
s = "";
while (A >= radix) {
s += hex[A % radix];
A = Math.floor(A / radix);
}
return transpose(s += hex);
}
function transpose(s) {
N = s.length;
for (i = 0,t = ""; i < N; i++)
t += s.substring(N-i-1, N-i);
return t;
}
function EvalAny(item, r) {
M = CKparseInt(item.value, r);
for (var i = 0, MyForm = document.forms; i < MyForm.length; ++i)
MyForm.elements.value = DecimaltoAnother(M, MyForm.elements.name.substr(1,3));
}
</script>
<center>
<h3>进制转换</h3>
<br>
<form method="post">
<table border=0 align=center>
<tr>
<td align=right>
<p>二进制:</p>
</td>
<td><input name="b002" value="0" onChange="EvalAny(this, 2)" size=27></td>
</tr>
<tr>
<td align=right>三进制:</td>
<td><input name="t003" value="0" onChange="EvalAny(this, 3)" size=21></td>
</tr>
<tr>
<td align=right>五进制:</td>
<td><input name="q005" value="0" onChange="EvalAny(this, 5)" size=16></td>
</tr>
<tr>
<td align=right>八进制:</td>
<td><input name="o008" value="0" onChange="EvalAny(this, 8)" size=12></td>
</tr>
<tr>
<td align=right>十进制:</td>
<td><input name="d010" value="0" onChange="EvalAny(this, 10)" size=11></td>
</tr>
<tr>
<td align=right>十六进制:</td>
<td><input name="h016" value="0" onChange="EvalAny(this, 16)" size=8></td>
</tr>
</table>
</form>
</center>



  一份编码对照表:
  http://www.ansell-uebersetzungen.com/gbuni.html
  准备好以后,我们就开始DIY匹配UTF-8中文字符的正则表达式,有能力的朋友可以不阅读下面的文章,自己对照正则表达式判断和分析过程(我一开始就是这么做的!),下面的进度比较快,对编码不了解的朋友需要借助参考资料阅读。
  仔细研究《编码对照表》,你会发现unicode编码中的汉字编码区间是连续的,位于4E00和9FA0之间,用《进制转换页面》把16进制转换成2进制:

4E00 :0100 1110 0000 0000
9FA0 :1001 1111 1010 0000

  上面的二进制编码就是要写入1 1 1 0 _ _ _ _ 1 0 _ _ _ _ _ _ 1 0 _ _ _ _ _ _ 的16个空位,就像:

1110 0100 1011 1000 1000 0000
1110 1001 1011 1110 1010 0000

  将新组成的2进制形式UTF-8编码使用《进制转换页面》整理成16进制的(分析过程使用)格式:

1110 0100 1011 1000 1000 0000 : E4 B8 80
1110 1001 1011 1110 1010 0000 : E9 BE A0

  精确拆分的结果如下:
  第一段:E4 B8 80 到 E4 BF BF
第二段:E5 80 80 到 E8 BF BF
第三段:E9 80 80 到 E9 BE A0
  正则的作者显然是为了编写的方便,将汉字的UTF-8编码集扩大为了:E4 80 80 到 E9 BF BF ,在对使用效果影响不大的情况下,我们也不妨简化处理:
  [".chr(228)."-".chr(233)."]{1}表示一个E4(228的16进制表示)到E9之间的编码,[".chr(128)."-".chr(191)."]{1}表示80到BF之间的编码,于是就组成了 ([".chr(228)."-".chr(233)."]{1}[".chr(128)."-".chr(191)."]{1}[".chr(128)."-".chr(191)."]{1}){1}这个匹配UTF-8单个汉字的正则,最后经过修正,成为本文开始给出的表达式。
  http://www.csask.com/blog/?p=20







php 扩展正则表达式函数 ereg



要激活 regexp 的支持在配置 PHP 时加上 --with-regex[=TYPE]。TYPE 可以是 system,apache 或 php 之一。默认使用 php。

PHP 的 Windows 版本已经内置该扩展模块的支持。无需加载任何附加扩展库即可使用这些函数。

运行时配置
本扩展模块在 php.ini 中未定义任何配置选项。

资源类型
本扩展模块未定义任何资源类型。

预定义常量
本扩展模块未定义任何常量。

范例
例子 1. 正则表达式例子


view plaincopy to clipboardprint?





[*]
<?php
[*]
//如果在$string中任何地方找到"abc"则返回&true;
[*]
ereg("abc",$string);
[*]

[*]
//如果$string以"abc"开头则返回&true;
[*]
ereg("^abc",$string);
[*]

[*]
//如果$string以"abc"结尾则返回&true;
[*]
ereg("abc$",$string);
[*]

[*]
//如果用户浏览器是Netscape2,3或MSIE3则返回&true;
[*]
eregi("(ozilla.|MSIE.3)",$HTTP_USER_AGENT);
[*]

[*]
//将三个空格分隔的单词放入$regs,$regs和$regs中
[*]
ereg("([[:alnum:]]+)([[:alnum:]]+)([[:alnum:]]+)",$string,$regs);
[*]

[*]
//将<br/>标记放到$string开头
[*]
$string=ereg_replace("^","<br/>",$string);
[*]

[*]
//将<br/>标记放到$string结尾
[*]
$string=ereg_replace("$","<br/>",$string);
[*]

[*]
//删除$string中的所有换行符
[*]
$string=ereg_replace("/n","",$string);
[*]?>
页: [1]
查看完整版本: PHP匹配UTF-8中文字符的正则表达式