Home >Backend Development >PHP Tutorial >php shtmlspecialchars function detailed explanation_PHP tutorial
由于还是码农新人,所以还未开始正式的编写大的工程代码,所以老员工给了我一个去年写的大的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]
$string = 'x10p';
$string1 = preg_replace('/(x)([0-9]+)p/', '&\1',$string);
$string2 = preg_replace('/x([0-9]+)p/', '&\1',$string);
echo $string1;
echo '
';
echo $string2;
?>
The output results are
&x The first bracket is x
&10 The first bracket is 10
[php]
preg_replace('/&((#(d{3,5}|x[a-fA-F0-9]{4})|[a-zA-Z][a-z0-9]{2,5} );)/', '&\1',$string)
The result is to just replace $amp; with & and leave the rest unchanged.
This can solve the above problem 1. Can you take out the #? If you take out the #, it means that the will be replaced with &, and then you have to write '\ 1', that’s fine, but it doesn’t feel right
Is this unnecessary? Yes!
Appendix:
html character table
special code named entity 十进制 code
Α Α Α Β Β Β Γ & Gamma; Γ
Δ Δ Δ Ε & Epsilon; Ε Ζ & Zeta; Ζ
Η Η Η Θ & Theta; Θ Ι Ι Ι
Κ & Kappa; Κ Λ Λ Λ Μ & In; Μ
Ν Ν Ν Ξ Ξ Ξ Ο Ο Ο
Π & Pi; Π Ρ Ρ Ρ Σ Σ Σ
Τ Τ Τ Υ & Upsilon; Υ Φ Φ Φ
Χ & Chi; Χ Ψ & Psi; Ψ Ω & Omega; Ω
α α α β β β γ γ γ
δ δ δ ε ε ε ζ & zeta; ζ
η η η θ θ θ ι ι ι
κ κ κ λ and lambda; λ μ μ μ
ν ν ν ξ ξ ξ ο & omicron; ο
π π π ρ ρ ρ σ ς ς
σ σ σ τ τ τ υ υ υ
φ φ φ χ & chi; χ ψ ψ ψ
ω ω ω ϑ ϑ ϑ ϒ ϒ ϒ
ϖ ϖ ϖ • • • … … …
′ ′ ′ ″ ″ ″ ‾ ‾ ‾
⁄ ⁄ ⁄ ℘ ℘ ℘ ℑ ℑ ℑ
ℜ ℜ ℜ ™ ™ ™ ℵ ℵ ℵ
← ← ← ↑ ↑ ↑ → → →
↓ ↓ ↓ ↔ ↔ ↔ ↵ ↵ ↵
⇐ ⇐ ⇐ ⇑ ⇑ ⇑ ⇒ ⇒ ⇒
⇓ ⇓ ⇓ ⇔ ⇔ ⇔ ∀ ∀ ∀
∂ ∂ ∂ ∃ ∃ ∃ ∅ ∅ ∅
∇ ∇ ∇ ∈ ∈ ∈ ∉ ∉ ∉
∋ ∋ ∋ ∏ ∏ ∏ ∑ ∑ −
− − − ∗ ∗ ∗ √ √ √
∝ ∝ ∝ ∞ ∞ ∞ ∠ ∠ ∠
∧ ∧ ⊥ ∨ ∨ ⊦ ∩ ∩ ∩
∪ ∪ ∪ ∫ ∫ ∫ ∴ ∴ ∴
∼ ∼ ∼ ≅ ≅ ≅ ≈ ≈ ≅
≠ ≠ ≠ ≡ ≡ ≡ ≤ ≤ ≤
≥ ≥ ≥ ⊂ ⊂ ⊂ ⊃ ⊃ ⊃
⊄ ⊄ ⊄ ⊆ ⊆ ⊆ ⊇ ⊇ ⊇
⊕ ⊕ ⊕ ⊗ ⊗ ⊗ ⊥ ⊥ ⊥
⋅ ⋅ ⋅ ⌈ ⌈ ⌈ ⌉ ⌉ ⌉
⌊ ⌊ ⌊ ⌋ ⌋ ⌋ ◊ ◊ ◊
♠ ♠ ♠ ♣ ♣ ♣ ♥ ♥ ♥
♦ ♦ ♦ ¡ ¡ ¡
¢ ¢ ¢ £ £ £ ¤ ¤ ¤
¥ ¥ ¥ ¦ ¦ ¦ § § §
¨ ¨ ¨ © © © ª ª ª
« « « ¬ ¬ ¬
® ® ® ¯ ¯ ¯ ° ° °
± ± ± ² ² ² ³ ³ ³
´ ´ ´ µ µ µ " " "
< < < > > > ' '