nginx rewrite 中文URL怎么转
请问下各位前辈,nginx rewrite 中文URL怎么转?
比如:
/search-50-中国 转发到 /search.php?keywords=中国
这个keywords是用户输入的中文,可能是中文、英文、带符号的,这里面这个正则咋写?pcre好像不支持u
汉字的编码有很多种,常见的三种是gb2312、utf8、unicode编码
实际使用中有urlencode、json_encode、base64()
urlencode的代码结果是%+两个字母的形式,如:
json_encode的汉子结果是u开头接着四个数字或字母的组合
base64的汉子编码邮件中常见
Unicode编码表
Unicode只有一个字符集,中、日、韩的三种文字占用了Unicode中0x3000到0x9FFF的部分
Unicode目前普遍采用的是UCS-2,它用两个字节来编码一个字符, 比如汉字"经"的编码是0x7ECF,注意字符编码一般用十六进制来 表示,为了与十进制区分,十六进制以0x开头,0x7ECF转换成十进制 就是32463,UCS-2用两个字节来编码字符,两个字节就是16位二进制, 2的16次方等于65536,所以UCS-2最多能编码65536个字符。 编码从0到127的字符与ASCII编码的字符一样,比如字母"a"的Unicode 编码是0x0061,十进制是97,而"a"的ASCII编码是0x61,十进制也是97, 对于汉字的编码,事实上Unicode对汉字支持不怎么好,这也是没办法的, 简体和繁体总共有六七万个汉字,而UCS-2最多能表示65536个,才六万 多个,所以Unicode只能排除一些几乎不用的汉字,好在常用的简体汉字 也不过七千多个,为了能表示所有汉字,Unicode也有UCS-4规范,就是用 4个字节来编码字符,不过现在普遍采用的还是UCS-2,只用两个字节来 编码,汉字的正则表达式范围为[u4e00-u9fa5]
重复一遍,这里的关系是,UTF-8是Unicode的实现方式之一,它规定了字符如何在计算机中存储、传输等。
UTF-8最大的一个特点,就是它是一种变长的编码方式。它可以使用1~4个字节表示一个符号,根据不同的符号而变化字节长度。
UTF-8的编码规则很简单,只有二条:
1)对于单字节的符号,字节的第一位设为0,后面7位为这个符号的unicode码。因此对于英语字母,UTF-8编码和ASCII码是相同的。
2)对于n字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的unicode码。
下表总结了编码规则,字母x表示可用编码的位。
Unicode符号范围 | UTF-8编码方式
(十六进制) | (二进制)
--------------------+---------------------------------------------
0000 0000-0000 007F | 0xxxxxxx
0000 0080-0000 07FF | 110xxxxx 10xxxxxx
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
下面,还是以汉字“严”为例,演示如何实现UTF-8编码。
已知“严”的unicode是4E25(100111000100101),根据上表,可以发现4E25处在第三行的范围内(0000 0800-0000 FFFF),因此“严”的UTF-8编码需要三个字节,即格式是“1110xxxx 10xxxxxx 10xxxxxx”。然后,从“严”的最后一个二进制位开始,依次从后向前填入格式中的x,多出的位补0。这样就得到了,“严”的UTF-8编码是“11100100 10111000 10100101”,这是保存在计算机中的实际数据,转换成十六进制就是E4B8A5,转成十六进制的目的为了便于阅读。
6. Unicode与UTF-8之间的转换
通过上一节的例子,可以看到“严”的Unicode码是4E25,UTF-8编码是E4B8A5,两者是不一样的。它们之间的转换可以通过程序实现。
在Windows平台下,有一个最简单的转化方法,就是使用内置的记事本小程序Notepad.exe。打开文件后,点击“文件”菜单中的“另存为”命令,会跳出一个对话框,在最底部有一个“编码”的下拉条。
里面有四个选项:ANSI,Unicode,Unicode big endian 和 UTF-8。
1)ANSI是默认的编码方式。对于英文文件是ASCII编码,对于简体中文文件是GB2312编码(只针对Windows简体中文版,如果是繁体中文版会采用Big5码)。
2)Unicode编码指的是UCS-2编码方式,即直接用两个字节存入字符的Unicode码。这个选项用的little endian格式。
3)Unicode big endian编码与上一个选项相对应。我在下一节会解释little endian和big endian的涵义。
4)UTF-8编码,也就是上一节谈到的编码方法。
选择完”编码方式“后,点击”保存“按钮,文件的编码方式就立刻转换好了。
7. Little endian和Big endian
上一节已经提到,Unicode码可以采用UCS-2格式直接存储。以汉字”严“为例,Unicode码是4E25,需要用两个字节存储,一个字节是4E,另一个字节是25。存储的时候,4E在前,25在后,就是Big endian方式;25在前,4E在后,就是Little endian方式。
那么很自然的,就会出现一个问题:计算机怎么知道某一个文件到底采用哪一种方式编码?
Unicode规范中定义,每一个文件的最前面分别加入一个表示编码顺序的字符,这个字符的名字叫做”零宽度非换行空格“(ZERO WIDTH NO-BREAK SPACE),用FEFF表示。这正好是两个字节,而且FF比FE大1。
如果一个文本文件的头两个字节是FE FF,就表示该文件采用大头方式;如果头两个字节是FF FE,就表示该文件采用小头方式。
8. 实例
下面,举一个实例。
打开”记事本“程序Notepad.exe,新建一个文本文件,内容就是一个”严“字,依次采用ANSI,Unicode,Unicode big endian 和 UTF-8编码方式保存。
然后,用文本编辑软件UltraEdit中的”十六进制功能“,观察该文件的内部编码方式。
1)ANSI:文件的编码就是两个字节“D1 CF”,这正是“严”的GB2312编码,这也暗示GB2312是采用大头方式存储的。
2)Unicode:编码是四个字节“FF FE 25 4E”,其中“FF FE”表明是小头方式存储,真正的编码是4E25。
3)Unicode big endian:编码是四个字节“FE FF 4E 25”,其中“FE FF”表明是大头方式存储。
4)UTF-8:编码是六个字节“EF BB BF E4 B8 A5”,前三个字节“EF BB BF”表示这是UTF-8编码,后三个“E4B8A5”就是“严”的具体编码,它的存储顺序与编码顺序是一致的。
GBK与UTF-8的区别
GBK的文字编码是双字节来表示的,即不论中、英文字符均使用双字节来表示,只不过为区分中文,将其最高位都定成1。 | 至于UTF-8编码则是用以解决国际上字符的一种多字节编码,它对英文使用8位(即一个字节),中文使用24位(三个字节)来编码。对于英文字符较多的论坛则用UTF-8节省空间。 |
GBK包含全部中文字符; | UTF-8则包含全世界所有国家需要用到的字符。 |
GBK是在GB2312基础上扩容后兼容GB2312的标准; | UTF-8编码的文字可以在各国各种支持UTF8字符集的浏览器上显示。 |
GBK是国家编码,通用性比UTF8差,不过UTF8占用的数据库比GBK大; | UTF-8是国际编码,它的通用性比较好,外国人也可以浏览论坛。 |
现在的网站程序都会出好几种编码的版本,如utf8、gbk、big5等。特别是utf8和gbk两种编码,常常让新手站长无从下手。
在中国区域内GB通用一些,而UTF8的国际通用一些。我们能够正常浏览到韩国、日本的网站,其实正常浏览的这些网站都是采用UTF8的格式。
我们打开各大型网站现在普遍采用的都是 GB 格式,例如百度、QQ、163、discuz、phpwind等,而少部分使用UTF例如google。
非特殊情况下很少有外文操作系统来访问一般的中文站点的,而当你规模大了后在转换也不迟。经常访问中文的外国朋友,他们一定会在自己的操作系统里面安装GB相关的支持插件或补丁的。所以这个不用担心。
GBK与UTF-8的区别
GBK的文字编码是双字节来表示的,即不论中、英文字符均使用双字节来表示,只不过为区分中文,将其最高位都定成1。 | 至于UTF-8编码则是用以解决国际上字符的一种多字节编码,它对英文使用8位(即一个字节),中文使用24位(三个字节)来编码。对于英文字符较多的论坛则用UTF-8节省空间。 |
GBK包含全部中文字符; | UTF-8则包含全世界所有国家需要用到的字符。 |
GBK是在GB2312基础上扩容后兼容GB2312的标准; | UTF-8编码的文字可以在各国各种支持UTF8字符集的浏览器上显示。 |
GBK是国家编码,通用性比UTF8差,不过UTF8占用的数据库比GBK大; | UTF-8是国际编码,它的通用性比较好,外国人也可以浏览论坛。 |
比如,如果是UTF8编码,则在外国人的英文IE上也能显示中文,而无需他们下载IE的中文语言支持包。 所以,对于英文比较多的论坛 ,使用GBK则每个字符占用2个字节,而使用UTF-8英文却只占一个字节。
对于Discuz论坛来说,很多插件都只支持GBK的,如果需要装较多插件的论坛还是用GBK比较好,而对装较少插件且有特殊用户群的论坛用UTF8比较好。
GB2312是GBK的子集,GBK是GB18030的子集。GBK是包括中日韩字符的大字符集合。如果是中文的网站推荐GB2312、GBK有时还是有一些问题。为了避免所有乱码问题,应该采用UTF-8,将来要支持国际化也非常方便。UTF-8可以看作是大字符集,它包含了大部分文字的编码。使用UTF-8的一个好处是其他地区的用户(如香港台湾)无需安装简体中文支持就能正常观看你的文字而不会出现乱码。
UTF8
UTF8并不算是一种电脑编码,而是一种储存和传送的格式,如前所述,每个Unicode/UCS字符都以 2或4个bytes来储存,看看以下的比较:
以"I am Chinese"为例 | 以"我是中国人"为例 |
用ANSI储存:12 Bytes | 用ANSI储存:10 Bytes |
用Unicode/UCS2储存:24 Bytes + 2 Bytes(header) | 用Unicode/UCS2储存:10 Bytes + 2 Bytes(header) |
用UCS4储存:48 Bytes + 4 Bytes(header) | 用UCS4储存:20 Bytes + 4 Bytes(header) |
由此可见直接以Unicode/UCS的原始形式来储存是一种极大的浪费,而且也不利于互联网的传输(中文稍为合算一点)。
有见及此,Unicode/UCS的压缩形式--UTF8出现了,套用官方网站的首句话『UTF-8 stands for Unicode Transformation Format-8. It is an octet (8-bit) lossless encoding of Unicode characters.』,由于UTF也适用于编码UCS,故亦可称为『UCS transformation formats (UTF)』
UTF8是以8bits即1Bytes为编码的最基本单位,当然也可以有基于16bits和32bits的形式,分别称为UTF16和UTF32,但目前用得不多,而UTF8则被广泛应用在文件储存和网络传输中。
以下是一些统计资料,显示用UTF8来储存文件每个字符所需的平均字节:
- 1.拉丁语系平均用1.1 Bytes;
- 2.希腊文、俄文、阿拉伯文和希伯莱文平均用1.7 Bytes;
- 3.其他大部份文字如中文、日文、韩文、Hindi(北印度语)用约3 Bytes;
- 4.用超过4 Bytes的都是些非常少用的文字符号。
GB2312
字符必须编码后才能被计算机处理。计算机使用的缺省编码方式就是计算机的内码。早期的计算机使用7位的ASCII编码,为了处理汉字,程序员设计了用于简体中文的GB2312和用于繁体中文的big5。
GB2312(1980年)一共收录了7445个字符,包括6763个汉字和682个其它符号。汉字区的内码范围高字节从B0-F7,低字节从A1-FE,占用的码位是72*94=6768。其中有5个空位是D7FA-D7FE。
GB2312支持的汉字太少。1995年的汉字扩展规范GBK1.0收录了21886个符号,它分为汉字区和图形符号区。汉字区包括21003个字符。2000年的GB18030是取代GBK1.0的正式国家标准。该标准收录了27484个汉字,同时还收录了藏文、蒙文、维吾尔文等主要的少数民族文字。现在的PC平台必须支持GB18030,对嵌入式产品暂不作要求。所以手机、MP3一般只支持GB2312。
从ASCII、GB2312、GBK到GB18030,这些编码方法是向下兼容的,即同一个字符在这些方案中总是有相同的编码,后面的标准支持更多的字符。在这些编码中,英文和中文可以统一地处理。区分中文编码的方法是高字节的最高位不为0。按照程序员的称呼,GB2312、GBK到GB18030都属于双字节字符集 (DBCS)。
有的中文Windows的缺省内码还是GBK,可以通过GB18030升级包升级到GB18030。不过GB18030相对GBK增加的字符,普通人是很难用到的,通常我们还是用GBK指代中文Windows内码。
Big5
大五码(Big5),又称为五大码,是使用繁体中文社群中最常用的电脑汉字字符集标准,共收录13,060个中文字,其中有二字为重覆编码,Big5属中文内码(中文码分为中文内码及中文交换码两类)。Big5虽普及于我国的台湾、香港与澳门等繁体中文通行区,但长期以来并非当地的国家标准,而只是业界标准(de facto standard)。倚天中文系统、Windows等主要系统的字符集都是以Big5为基准,但厂商又各自增删,衍生成多种不同版本。
2003年,Big5被收录到台湾官方标准的附录当中,取得了较正式的地位。这个最新版本被称为Big5-2003。
UNICODE、GBK、UTF-8区别
简单来说,unicode,gbk和大五码就是编码的值,而utf-8,uft-16之类就是这个值的表现形式.而前面那三种编码是一兼容的,同一个汉字,那三个码值是完全不一样的.如“汉”的uncode值与gbk就是不一样的,假设uncode为a040,gbk为b030,而uft-8码,就是把那个值表现的形式.utf-8码完全只针对uncode来组织的,如果gbk要转utf-8必须先转uncode码,再转utf-8就OK了。
字符必须编码后才能被计算机处理。计算机使用的缺省编码方式就是计算机的内码。早期的计算机使用7位的ASCII编码,为了处理汉字,程序员设计了用于简体中文的GB2312和用于繁体中文的big5。
从ASCII、GB2312到GBK,这些编码方法是向下兼容的,即同一个字符在这些方案中总是有相同的编码,后面的标准支持更多的字符。在这些编码中,英文和中文可以统一地处理。区分中文编码的方法是高字节的最高位不为0。按照程序员的称呼,GB2312、GBK都属于双字节字符集 (DBCS)。
2000年的GB18030是取代GBK1.0的正式国家标准。该标准收录了27484个汉字,同时还收录了藏文、蒙文、维吾尔文等主要的少数民族文字。从汉字字汇上说,GB18030在GB13000.1的20902个汉字的基础上增加了CJK扩展A的6582个汉字(Unicode码0x3400-0x4db5),一共收录了27484个汉字。
CJK就是中日韩的意思。Unicode为了节省码位,将中日韩三国语言中的文字统一编码。GB13000.1就是ISO/IEC 10646-1的中文版,相当于Unicode 1.1。
GB18030的编码采用单字节、双字节和4字节方案。其中单字节、双字节和GBK是完全兼容的。4字节编码的码位就是收录了CJK扩展A的6582个汉字。 例如:UCS的0x3400在GB18030中的编码应该是8139EF30,UCS的0x3401在GB18030中的编码应该是8139EF31。
微软提供了GB18030的升级包,但这个升级包只是提供了一套支持CJK扩展A的6582个汉字的新字体:新宋体-18030,并不改变内码。Windows 的内码仍然是GBK。
所谓代码页(code page)就是针对一种语言文字的字符编码。例如GBK的code page是CP936,BIG5的code page是CP950,GB2312的code page是CP20936。
Windows中有缺省代码页的概念,即缺省用什么编码来解释字符。例如Windows的记事本打开了一个文本文件,里面的内容是字节流:BA、BA、D7、D6。Windows应该去怎么解释它呢?
是按照Unicode编码解释、还是按照GBK解释、还是按照BIG5解释,还是按照ISO8859-1去解释?如果按GBK去解释,就会得到“汉字”两个字。按照其它编码解释,可能找不到对应的字符,也可能找到错误的字符。所谓“错误”是指与文本作者的本意不符,这时就产生了乱码。
答案是Windows按照当前的缺省代码页去解释文本文件里的字节流。缺省代码页可以通过控制面板的区域选项设置。记事本的另存为中有一项ANSI,其实就是按照缺省代码页的编码方法保存。
Windows的内码是Unicode,它在技术上可以同时支持多个代码页。只要文件能说明自己使用什么编码,用户又安装了对应的代码页,Windows就能正确显示,例如在HTML文件中就可以指定charset。
有的HTML文件作者,特别是英文作者,认为世界上所有人都使用英文,在文件中不指定charset。如果他使用了0x80-0xff之间的字符,中文Windows又按照缺省的GBK去解释,就会出现乱码。这时只要在这个html文件中加上指定charset的语句,例如:
1 |
<meta http-equiv="Content-Type" content="text/html; charset=ISO8859-1"> |
如果原作者使用的代码页和ISO8859-1兼容,就不会出现乱码了。
Unicode,中文简称为“统一码、万国码”,给每个字符提供了一个唯一的数字,不论是什么平台,不论是什么程序,不论是什么语言。
UTF-8是针对Unicode的一种可变长度字符编码。它可以用来表示Unicode 标准中的任何字符,且与ASCII码兼容,是Unicode的一种变长度的编码表达方式。
Unicode和UTF-8之间的转换关系表 |
|
UCS-2编码 | UTF-8字节流 |
U-00000000 – U-0000007F: | 0xxxxxxx |
U-00000080 – U-000007FF: | 110xxxxx 10xxxxxx |
U-00000800 – U-0000FFFF: | 1110xxxx 10xxxxxx 10xxxxxx |
U-00010000 – U-001FFFFF: | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx |
U-00200000 – U-03FFFFFF: | 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx |
U-04000000 – U-7FFFFFFF: | 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx |
Unicode到UFT-8的转换过程实例:
1、 汉字“艺”的Unicode编码为827A;
2、 “827A”属于U+0800到U+FFFF区域,这表明它使用三字节:1110xxxx 10xxxxxx 10xxxxxx;
3、 十六进制的“0x827A”换算成二进制为1000 0010 0111 1010;
4、 这16位数(注1)按顺序放入“x”部分,结果为11101000 1000100110111010;
5、 该结果用十六进制表示为E8 89 BA,即为0xE8 0x89 0xBA(%E8%89%BA),这便是汉字“艺”的UTF-8编码。
6、维基百科(编码为UTF-8)的网址中所用到的汉字其实都转化为相应的UTF-8编码,比如“中国”的Unicode编码分别为“4E2D”和“56FD”,转换成UTF-8编码为“%E4%B8%AD%E5%9B%BD”,因此用http://zh.wikipedia.org/wiki/中国和http://zh.wikipedia.org/wiki/%E4%B8%AD%E5%9B%BD,访问结果是一样的。(如有需要Unicode 5.1版本完整版,可到官方网站下载)
注1:如不足16位的,则高位补“0”,如注意符号“ㄠ”,其Unicode码为3120,对应的二进制为11 0001 0010 0000,只有14位,则需补两个“0”,变成0011 0001 0010 0000,然后按顺序放入“x”部分,结果为11100011 10000100 10100000,对应的十六进制为E3 84 A0,最终“ㄠ”UTF-8码为%E3%84%A0。
注2:目前,Unicode码只设计到10FFFF,而实际上编码只到E01EF,不论是E01EF,还是10FFFF,都远小于1FFFFF(10FFFF与1FFFFF之间还有98,3040个空间可供使用),所以对于UTF-8编码来说,用4个字节的长度足以为世界上绝大部分字符编码。
注3:对于U+0080--U+07FF之间的各个字符来说,它们的UTF-8编码都是以%C或%D开始的,对于U+0800--U+FFFF之间的各个字符,它们的UTF-8编码都是以%E开始的,而对于编码大于U+FFFF(即Unicode编码在FFFF之后)的所有字符的UTF-8都是以%F开始的。
重了,前后两个区别对比的表格。。