1. 程式人生 > >lua匹配UTF-8中文漢字

lua匹配UTF-8中文漢字

lua5.3雖然支援utf-8,但是自帶的string庫不支援漢字的處理,而且lua的正則實現也比較雞肋,很難匹配中文。所以文章討論UTF-8字符集,中文漢字的表示方法,然後說明lua如何匹配UTF-8中文漢字。

初識UTF-8

UTF-8是Unicode的一種實現,是一種變長位元組編碼方式。對於某一個字元的UTF-8編碼,如果只有一個位元組則其最高二進位制位為0;如果是多位元組,其第一個位元組從最高位開始,連續的二進位制位值為1的個數決定了其編碼的位數,其餘各位元組均以10開頭。UTF-8最多可用到6個位元組。 如表:
因此,UTF-8可以用來表示字元編碼最多的有效位數是31位,即x代表的位。除掉那些標誌位(如每位元組開頭的10),UTF-8表示的與Unicode編碼是對應的。另外,Unicode相容標準的ASCII字符集,只需要一個位元組就可以表示所有ASCII碼,ASCII碼一共規定了128個字元的編碼,所以實際只要7位表示。而對於1位元組表示的UTF-8編碼,位元組開頭是0,所以UTF-8表示的英文數字,跟ASCII字符集表示的是一樣的。

中文UTF-8

通常都說到,漢字範圍從0x4E00到0x9FA5,這是指Unicode編碼。對於UTF-8還要做轉換。其中,0x4E00 用二進位制表示為  100111000000000
換成UTF-8碼就是 11100100 10111000 10000000,即 228, 184, 128同理,0x9FA5為  11101001 10111110 10100101,即 233, 190, 165可以看出,中文UTF-8編碼用3個位元組表示。


lua匹配UTF-8漢字

前面分析了中文UTF-8的編碼範圍了,所以lua只要用 string.byte(s, i) 取到字元的byte值(字符集通常記 code point)。比較第一個位元組是228-233,而且接下來兩個位元組都是 128-191,就可以簡單認定為中文了。這裡以一個例子說明,比如我要過濾特殊字元,保留中文、英文和數字。
function filter_spec_chars(s)
	local ss = {}
	local k = 1
	while true do
		if k > #s then break end
		local c = string.byte(s,k)
		if not c then break end
		if c<192 then
			if (c>=48 and c<=57) or (c>= 65 and c<=90) or (c>=97 and c<=122) then
				table.insert(ss, string.char(c))
			end
			k = k + 1
		elseif c<224 then
			k = k + 2
		elseif c<240 then
			if c>=228 and c<=233 then
				local c1 = string.byte(s,k+1)
				local c2 = string.byte(s,k+2)
				if c1 and c2 then
					local a1,a2,a3,a4 = 128,191,128,191
					if c == 228 then a1 = 184
					elseif c == 233 then a2,a4 = 190,c1 ~= 190 and 191 or 165
					end
					if c1>=a1 and c1<=a2 and c2>=a3 and c2<=a4 then
						table.insert(ss, string.char(c,c1,c2))
					end
				end
			end
			k = k + 3
		elseif c<248 then
			k = k + 4
		elseif c<252 then
			k = k + 5
		elseif c<254 then
			k = k + 6
		end
	end
	return table.concat(ss)
end

最後語

題外話,前面寫的過濾特殊字元函式,用lua寫效率不高,所以我還寫了c的版本,有興趣猛擊這裡2016/10/14 修復中文匹配bug,感謝sishui的提示2017/3/2 修正臨時變數k不起作用的問題,提升了效率參考:http://blog.csdn.net/mycwq/article/details/51303353
http://www.cnblogs.com/chenwenbiao/archive/2011/08/11/2134503.html