htmlspecialchars 详解

作者:林子木  wolinxuebin

转载请保留:http://blog.csdn.net/wolinxuebin

    由于还是码农新人,所以还未开始正式的编写大的工程代码,所以老员工给了我一个去年写的大的PHP工程的工程代码,先看下。抱着必须扫清每个死角的心里,下午碰到了

shtmlspecialchars()函数,网上一查挺多人都在用的,但不是PHP自带的,而是莫比较官方的写的。但是这里面的正则表达式着实让我纠结了一方,不讲废话了,切入正题。

[php]  view plain copy
  1. function shtmlspecialchars($string) {  
  2.     if(is_array($string)) {  
  3.         foreach($string as $key => $val) {  
  4.             $string[$key] = shtmlspecialchars($val);  
  5.         }  
  6.     } else {  
  7.         $string = preg_replace('/&((#(\d{3,5}|x[a-fA-F0-9]{4})|[a-zA-Z][a-z0-9]{2,5});)/''&\\1',  
  8.             str_replace(array('&''"''<''>'), array('&amp;''&quot;''&lt;''&gt;'), $string));  
  9.     }  
  10.     return $string;  
  11. }  

以上就是shtmlspecialchars()函数的定义,其他的不讲,就讲这句让很多人揪心的

[php]  view plain copy
  1. $string = preg_replace('/&((#(\d{3,5}|x[a-fA-F0-9]{4})|[a-zA-Z][a-z0-9]{2,5});)/''&\\1',  
  2.             str_replace(array('&''"''<''>'), array('&''"''<''>'), $string));  


这里先介绍下这个函数的作用


html中可能出现的四种特殊字符进行转义,分别是

&转&amp;

"转&quot;

<转&lt;

>转&lt;(ps:这个后面的分号";"是连在一起的,一个整体,不是作者为了分隔用的)


这与PHP自带的htmlspecialchars()效果刚好相反。



那么一般人里面会用下面的代码实现这个函数所要实现的功能

[php]  view plain copy
  1. str_replace(array('&''"''<''>'), array('&''"''<''>'), $string));  

但是 等一等!


问:等什么?不是已经完成了这个功能了?

答:错,大错,特错了,你这叫宁可枉杀3000,不放过一个,不人道的呀。

问:哪里错了?

答:情况下面的内容!

如果仅仅用上面的函数,那么会将 html特殊字符和unicode编码 都破坏掉这可不是我们要的结果,具体字符表见文章后面的 附件

有人观察了字符表的所有数据,最后得出下面的结论:

1、 html特殊字符都是由&#开头后面加3-5个数字或者&#开头加一个字符和2-5个字符或数字组成的字符串
2、 unicode编码是以&#开头后面加4个16进制数字组成的字符串。


根据第一条, 我们应该写出正则表达式:&#/d{3,5}|[a-zA-Z][a-zA-Z0-9]{2,5};(ps:这个也是自带分号";"的)

根据第二条 ,可以得出&#[a-fA-F0-9]{4}; (ps:因为16进制是从0-f)


又由于前面的操作已经把&替换成了&amp;所以讲上面两条整合下就出了下面的

/&amp;((#(\d{3,5}|x[a-fA-F0-9]{4})|[a-zA-Z][a-z0-9]{2,5});)/


问题1:
有人问,是不是可以写成下面的样子

/&amp;#(((\d{3,5}|x[a-fA-F0-9]{4})|[a-zA-Z][a-z0-9]{2,5});)/

把井号提出来,当然可以,不过如果你要这样写,后面的再提,有些下改动。

我们把第一步操作

[php]  view plain copy
  1. str_replace(array('&''"''<''>'), array('&''"''<''>'), $string));  

结果写成$string

那么反替换我们就可以简略的写成

preg_replace('/&amp;((#(\d{3,5}|x[a-fA-F0-9]{4})|[a-zA-Z][a-z0-9]{2,5});)/', '&\\1',$string)

这里,前面的正则表达式已经很清楚了,但是作者又后面的&\\1搞晕了,什么意思呀?

经查证\1代表正则表达式的第一个括号内的内容。

自己写了一个测试

[php]  view plain copy
  1. <?php   
  2.   
  3. $string = 'x10p';  
  4. $string1 = preg_replace('/(x)([0-9]+)p/''&\\1',$string);  
  5. $string2 = preg_replace('/x([0-9]+)p/''&\\1',$string);  
  6. echo $string1;  
  7. echo '<br />';  
  8. echo $string2;  
  9. ?>  

输出的结果分别是

&x        第一括号内的是 x
&10     第一括号内的是10
[php]  view plain copy
  1. preg_replace('/&((#(\d{3,5}|x[a-fA-F0-9]{4})|[a-zA-Z][a-z0-9]{2,5});)/''&\\1',$string)  

结果就是仅仅把$amp;替换为&而后面的保留不变。

到这可以解决上面的问题1,是否可以把#拿出来,如果你吧#拿出来的话,那么就是说会将&amp;#都用&替换,然后后面的你得写'&#\\1',这样就可以,不过是不是感觉

多此一举了?是的!

参考文献:


【1】 http://blog.csdn.net/wolinxuebin/article/details/7604194 《php正则表达式详解》


【2】http://www.jb51.net/onlineread/htmlchar.htm HTML字符表


【3】http://deerchao.net/tutorials/regex/regex.htm 30分钟正则表达式入门


【4】http://topic.csdn.net/u/20100426/15/391a9a98-a457-451a-84d3-92d8f60ff0c0.html   关于uchome函数里面的shtmlspecilachars的功能 【5】http://s.yanghao.org/program/viewdetail.php?i=8324 


附录:


                                   html 字符表

特殊符号命名实体十进制编码特殊符号命名实体十进制编码特殊符号命名实体十进制编码
Α &Alpha; &#913; Β &Beta; &#914; Γ &Gamma; &#915;
Δ &Delta; &#916; Ε &Epsilon; &#917; Ζ &Zeta; &#918;
Η &Eta; &#919; Θ &Theta; &#920; Ι &Iota; &#921;
Κ &Kappa; &#922; Λ &Lambda; &#923; Μ &Mu; &#924;
Ν &Nu; &#925; Ξ &Xi; &#926; Ο &Omicron; &#927;
Π &Pi; &#928; Ρ &Rho; &#929; Σ &Sigma; &#931;
Τ &Tau; &#932; Υ &Upsilon; &#933; Φ &Phi; &#934;
Χ &Chi; &#935; Ψ &Psi; &#936; Ω &Omega; &#937;
α &alpha; &#945; β &beta; &#946; γ &gamma; &#947;
δ &delta; &#948; ε &epsilon; &#949; ζ &zeta; &#950;
η &eta; &#951; θ &theta; &#952; ι &iota; &#953;
κ &kappa; &#954; λ &lambda; &#955; μ &mu; &#956;
ν &nu; &#957; ξ &xi; &#958; ο &omicron; &#959;
π &pi; &#960; ρ &rho; &#961; ς &sigmaf; &#962;
σ &sigma; &#963; τ &tau; &#964; υ &upsilon; &#965;
φ &phi; &#966; χ &chi; &#967; ψ &psi; &#968;
ω &omega; &#969; ϑ &thetasym; &#977; ϒ &upsih; &#978;
ϖ &piv; &#982; &bull; &#8226; &hellip; &#8230;
&prime; &#8242; &Prime; &#8243; &oline; &#8254;
&frasl; &#8260; &weierp; &#8472; &image; &#8465;
&real; &#8476; &trade; &#8482; &alefsym; &#8501;
&larr; &#8592; &uarr; &#8593; &rarr; &#8594;
&darr; &#8595; &harr; &#8596; &crarr; &#8629;
&lArr; &#8656; &uArr; &#8657; &rArr; &#8658;
&dArr; &#8659; &hArr; &#8660; &forall; &#8704;
&part; &#8706; &exist; &#8707; &empty; &#8709;
&nabla; &#8711; &isin; &#8712; &notin; &#8713;
&ni; &#8715; &prod; &#8719; &sum; &#8722;
&minus; &#8722; &lowast; &#8727; &radic; &#8730;
&prop; &#8733; &infin; &#8734; &ang; &#8736;
&and; &#8869; &or; &#8870; &cap; &#8745;
&cup; &#8746; &int; &#8747; &there4; &#8756;
&sim; &#8764; &cong; &#8773; &asymp; &#8773;
&ne; &#8800; &equiv; &#8801; &le; &#8804;
&ge; &#8805; &sub; &#8834; &sup; &#8835;
&nsub; &#8836; &sube; &#8838; &supe; &#8839;
&oplus; &#8853; &otimes; &#8855; &perp; &#8869;
&sdot; &#8901; &lceil; &#8968; &rceil; &#8969;
&lfloor; &#8970; &rfloor; &#8971; &loz; &#9674;
&spades; &#9824; &clubs; &#9827; &hearts; &#9829;
&diams; &#9830;   &nbsp; &#160; ¡ &iexcl; &#161;
¢ &cent; &#162; £ &pound; &#163; ¤ &curren; &#164;
¥ &yen; &#165; ¦ &brvbar; &#166; § &sect; &#167;
¨ &uml; &#168; © &copy; &#169; ª &ordf; &#170;
« &laquo; &#171; ¬ &not; &#172;   &shy; &#173;
® &reg; &#174; ¯ &macr; &#175; ° &deg; &#176;
± &plusmn; &#177; ² &sup2; &#178; ³ &sup3; &#179;
´ &acute; &#180; µ &micro; &#181 " &quot; &#34;
< &lt; &#60; > &gt; &#62; '   &#39;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值