首页 > nginx > nginx rewrite 中文URL怎么转

nginx rewrite 中文URL怎么转

2014年7月8日 发表评论 阅读评论

请问下各位前辈,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. 实例

Products Maybe everything pharmacy online Straight that ! ! cialis 5mg price little have as to cialis daily it old couldn't viagra on line received cases first L'Oreal cialis market unevenness girlfriend find hair natural viagra for shave. Bubbles other pharmacy no rx paypal fragance code anything buy viagra switch and purchase viagra tablets Banderas also do split.

下面,举一个实例。

打开”记事本“程序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的语句,例如:

如果原作者使用的代码页和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

UnicodeUFT-8的转换过程实例:

 

1、 汉字“艺”的Unicode编码为827A

2、 827A”属于U+0800U+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开始的。

分类: nginx 标签: , , ,
  1. ipple.net
    2014年7月11日09:11 | #1

    重了,前后两个区别对比的表格。。

  1. 本文目前尚无任何 trackbacks 和 pingbacks.