原文地址:http://blog.csdn.net/wolinxuebin
由於還是碼農新人,所以還未開始正式的編寫大的工程代碼,所以老員工給了我一個去年寫的大的PHP工程的工程代碼,先看下。抱著必須掃清每個死角的心裡,下午碰到了
shtmlspecialchars()函數,網上一查挺多人都在用的,但不是PHP內建的,而是莫比較官方的寫的。但是這裡面的Regex著實讓我糾結了一方,不講廢話了,切入正題。
[php] view plain copy 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] view plain copy $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] view plain copy str_replace(array('&', '"', '<', '>'), array('&', '"', '<', 'gt'), $string));
但是 等一等。
問:等什麼。不是已經完成了這個功能了。
答:錯,大錯,特錯了,你這叫寧可枉殺3000,不放過一個,不人道的呀。
問:哪裡錯了。
答:情況下面的內容。
如果僅僅用上面的函數,那麼會將 html特殊字元和unicode編碼 都破壞掉這可不是我們要的結果,具體字元表見文章後面的 附件 。
有人觀察了字元表的所有資料,最後得出下面的結論:
1、 html特殊字元都是由&#開頭後面加3-5個數字或者&#開頭加一個字元和2-5個字元或數字組成的字串
2、 unicode編碼是以&#開頭後面加4個16進位數字組成的字串。
根據第一條, 我們應該寫出Regex:&#/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});)/
把井號提出來,當然可以,不過如果你要這樣寫,後面的再提,有些下改動。
我們把第一步操作
str_replace ( array ( '&' , '"' , '<' , '>' ),