当前位置:编程学习 > php >>

php shtmlspecialchars 函数 详解

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

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

[php] 
function shtmlspecialchars($string) { 
    if(is_array($string)) { 
        foreach($string as $key => $val) { 
            $string[$key] = shtmlspecialchars($val); 
        } 
    } else { 
        $string = preg_replace('/&((#(\d{3,5}|x[a-fA-F0-9]{4})|[a-zA-Z][a-z0-9]{2,5});)/', '&\\1', 
            str_replace(array('&', '"', '<', '>'), array('&', '"', '<', '>'), $string)); 
    } 
    return $string; 

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

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


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

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

&转&

"转"

<转<

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


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


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

[php]
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)


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

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

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

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

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

我们把第一步操作
[php] 
str_replace(array('&', '"', '<', '>'), array('&', '"', '<', '>'), $string)); 

结果写成$string

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

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

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

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

自己写了一个测试

[php] 
<?php  
 
$string = 'x10p'; 
$string1 = preg_replace('/(x)([0-9]+)p/', '&\\1',$string); 
$string2 = preg_replace('/x([0-9]+)p/', '&\\1',$string); 
echo $string1; 
echo '<br />'; 
echo $string2; 
?> 

输出的结果分别是

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

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

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

多此一举了?是的!

 

附录:

 

                                   html 字符表

特殊符号 命名实体 十进制编码 特殊符号 命名实体 十进制编码 特殊符号 命名实体 十进制编码
Α  Α  Α  Β  Β  Β  Γ  Γ  Γ
Δ  Δ  Δ  Ε  Ε  Ε  Ζ  Ζ  Ζ
Η  Η  Η  Θ  Θ  Θ  Ι  Ι  Ι
Κ  Κ  Κ  Λ  Λ  Λ  Μ  Μ  Μ
Ν  Ν  Ν  Ξ  Ξ  Ξ  Ο  Ο  Ο
Π  Π  Π  Ρ  Ρ  Ρ  Σ  Σ  Σ
Τ  Τ  Τ  Υ  Υ  Υ  Φ  Φ  Φ
Χ  Χ  Χ  Ψ  Ψ  Ψ  Ω  Ω  Ω
α  α  α  β  β  β  γ  γ  γ
δ  δ  δ  ε  ε  ε  ζ  ζ  ζ
η  η  η  θ  θ  θ  ι  ι  ι
κ  κ  κ  λ  λ  λ  μ  μ  μ
ν  ν  ν  ξ  ξ  ξ  ο  ο  ο
π  π  π  ρ  ρ  ρ  ς  ς  ς
σ  σ  σ  τ  τ  τ  υ  υ  υ
φ  φ  φ  χ  χ  χ  ψ  ψ  ψ
ω  ω  ω  ϑ  ϑ  ϑ  ϒ  ϒ  ϒ
ϖ  ϖ  ϖ  •  •  •  …  …  …
′  ′  ̸

补充:Web开发 , php ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,