查看文章 |
急着用的朋友可以先拿去用,这个正则非原创,但是经过我的修改,如有问题,请回复告知,代码是写给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[A]); } 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[0]; i < MyForm.length; ++i) MyForm.elements[i].value = DecimaltoAnother(M, MyForm.elements[i].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 上面的二进制编码就是要写入1 1 1 0 _ _ _ _ 1 0 _ _ _ _ _ _ 1 0 _ _ _ _ _ _ 的16个空位,就像: 1110 0100 1011 1000 1000 0000 将新组成的2进制形式UTF-8编码使用《进制转换页面》整理成16进制的(分析过程使用)格式: 1110 0100 1011 1000 1000 0000 : E4 B8 80 精确拆分的结果如下: 第一段:E4 B8 80 到 E4 BF BF 正则的作者显然是为了编写的方便,将汉字的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单个汉字的正则,最后经过修正,成为本文开始给出的表达式。 |