Python实现全⾓半⾓字符互转的⽅法
前⾔
相信对于每⼀个编程⼈员来说,在⽂本处理的时候,经常会遇到全⾓半⾓不⼀致的问题。于是需要程序能够快速的在两者之间互转。由于全⾓半⾓本⾝存在着映射关系,所以处理起来并不复杂。
具体规则为:
全⾓字符unicode编码从65281~65374 (⼗六进制 0xFF01 ~ 0xFF5E)
半⾓字符unicode编码从33~126 (⼗六进制 0x21~ 0x7E)
空格⽐较特殊,全⾓为 12288(0x3000),半⾓为 32(0x20)
⽽且除空格外,全⾓/半⾓按unicode编码排序在顺序上是对应的(半⾓ + 65248 = 全⾓)
所以可以直接通过⽤+-法来处理⾮空格数据,对空格单独处理。
⽤到的⼀些函数
chr()函数⽤⼀个范围在range(256)内的(就是0~255)整数作参数,返回⼀个对应的字符。
unichr()跟它⼀样,只不过返回的是Unicode字符。
ord()函数是chr()函数或unichr()函数的配对函数,它以⼀个字符(长度为1的字符串)作为参数,返回对应的ASCII数值,或者Unicode数值。
先来打印下映射关系:
1 2for i in xrange(33,127):
print i,chr(i),i+65248,unichr(i+65248)
返回结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 3433! 65281!34" 65282"35# 65283 #36$ 65284$37%65285%38& 65286&39' 65287'40( 65288(41) 65289)42*65290*43+65291+44, 65292,45-65293-46. 65294.47/65295/48065296049165297150265298251365299352465300453565301554665302655765303756865304857965305958: 65306:59; 65307;60< 65308<61=65309=62> 65310>63? 65311?64@ 65312@65A 65313A66B 65314B
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 9466B 65314B67C 65315C68D 65316D69E 65317E70F 65318F71G 65319G72H 65320H73I 65321I74J 65322J75K 65323K76L 65324L77M 65325M78N 65326N79O 65327O80P 65328P81Q 65329Q82R 65330R83S 65331S84T 65332T85U 65333U86V 65334V87W 65335W88X 65336X89Y 65337Y90Z 65338Z91[ 65339[92\ 65340\93] 65341]94^ 65342^95_ 65343_96` 65344`97a 65345a98b 65346b99c 65347c100d 65348d101e 65349e102f 65350f103g 65351g104h 65352h105i 65353i106j 65354j107k 65355k108l 65356l109m 65357m110n 65358n111o 65359o112p 65360p113q 65361q114r 65362r115s 65363s116t 65364t117u 65365u118v 65366v119w 65367w120x 65368x121y 65369y122z 65370z
123{ 65371{124| 65372|125} 65373}126~ 65374~
把全⾓转成半⾓:
1 2 3 4 5 6def full2half(s):
n =[]
s =s.decode('utf-8') for char in s:
num =ord(char)
if num ==0x3000:
6 7 8 9 10 11 12 if num ==0x3000:
num =32
elif0xFF01<=num <=0xFF5E:  num -=0xfee0
num =unichr(num)
n.append(num)
return''.join(n)
把半⾓转成全⾓:
1 2 3 4 5 6 7 8 9 10 11 12def half2full(s):
n =[]
s =s.decode('utf-8')
for char in s:
num =char(char)
if num ==320:
num =0x3000
elif0x21<=num <=0x7E:  num +=0xfee0
num =unichr(num)
n.append(num)
return''.join(n)
上⾯的实现⽅式⾮常的简单,但是现实情况下可能并不会把所以的字符统⼀进⾏转换,⽐如中⽂⽂章中我们期望将所有出现的字母和数字全部转化成半⾓,⽽常见标点符号统⼀使⽤全⾓,上⾯的转化就不适合了。
解决⽅案,是⾃定义词典。
1
2
3
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41#!/usr/bin/env python
# -*- coding: utf-8 -*-
FH_SPACE =FHS =((u" ", u" "),)
FH_NUM =FHN =(
(u"0", u"0"), (u"1", u"1"), (u"2", u"2"), (u"3", u"3"), (u"4", u"4"),
(u"5", u"5"), (u"6", u"6"), (u"7", u"7"), (u"8", u"8"), (u"9", u"9"),
)
FH_ALPHA =FHA =(
(u"a", u"a"), (u"b", u"b"), (u"c", u"c"), (u"d", u"d"), (u"e", u"e"),
(u"f", u"f"), (u"g", u"g"), (u"h", u"h"), (u"i", u"i"), (u"j", u"j"),
(u"k", u"k"), (u"l", u"l"), (u"m", u"m"), (u"n", u"n"), (u"o", u"o"),
(u"p", u"p"), (u"q", u"q"), (u"r", u"r"), (u"s", u"s"), (u"t", u"t"),
(u"u", u"u"), (u"v", u"v"), (u"w", u"w"), (u"x", u"x"), (u"y", u"y"), (u"z", u"z"),
(u"A", u"A"), (u"B", u"B"), (u"C", u"C"), (u"D", u"D"), (u"E", u"E"),
(u"F", u"F"), (u"G", u"G"), (u"H", u"H"), (u"I", u"I"), (u"J", u"J"),
(u"K", u"K"), (u"L", u"L"), (u"M", u"M"), (u"N", u"N"), (u"O", u"O"),
(u"P", u"P"), (u"Q", u"Q"), (u"R", u"R"), (u"S", u"S"), (u"T", u"T"),
(u"U", u"U"), (u"V", u"V"), (u"W", u"W"), (u"X", u"X"), (u"Y", u"Y"), (u"Z", u"Z"),
)
FH_PUNCTUATION =FHP =(
(u".", u"."), (u",", u","), (u"!", u"!"), (u"?", u"?"), (u"”", u'"'),
(u"'", u"'"), (u"‘", u"`"), (u"@", u"@"), (u"_", u"_"), (u":", u":"),
(u";", u";"), (u"#", u"#"), (u"$", u"$"), (u"%", u"%"), (u"&", u"&"),
(u"(", u"("), (u")", u")"), (u"‐", u"-"), (u"=", u"="), (u"*", u"*"),
(u"+", u"+"), (u"-", u"-"), (u"/", u"/"), (u"<", u"<"), (u">", u">"),
(u"[", u"["), (u"¥", u"\\"), (u"]", u"]"), (u"^", u"^"), (u"{", u"{"),
(u"|", u"|"), (u"}", u"}"), (u"~", u"~"),
)
FH_ASCII =HAC =lambda: ((fr, to) for m in(FH_ALPHA, FH_NUM, FH_PUNCTUATION) for fr, to in m)
HF_SPACE =HFS =((u" ", u" "),)
HF_NUM =HFN =lambda: ((h, z) for z, h in FH_NUM)
HF_ALPHA =HFA =lambda: ((h, z) for z, h in FH_ALPHA)
HF_PUNCTUATION =HFP =lambda: ((h, z) for z, h in FH_PUNCTUATION)
HF_ASCII =ZAC =lambda: ((h, z) for z, h in FH_ASCII())
def convert(text, *maps, **ops):
""" 全⾓/半⾓转换
args:
text: unicode string need to convert
maps: conversion maps
skip: skip out of character. In a tuple or string
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 skip: skip out of character. In a tuple or string
return: converted unicode string
"""
if"skip"in ops:
skip =ops["skip"]
if isinstance(skip, basestring):
skip =tuple(skip)
def replace(text, fr, to):
unicode字符转中文return text if fr in skip place(fr, to)
else:
def replace(text, fr, to):
place(fr, to)
for m in maps:
if callable(m):
m =m()
elif isinstance(m, dict):
m =m.items()
for fr, to in m:
text =replace(text, fr, to)
return text
if__name__ =='__main__':
text =u"成⽥空港—【JR特急成⽥エクスプレス号·横浜⾏,2站】—東京—【JR新幹線はやぶさ号·新青森⾏,6站】—新青森—【JR特急スーパー⽩⿃号·函館⾏,4站】—函館"
print convert(text, FH_ASCII, {u"【": u"[", u"】": u"]", u",": u",", u".": u"。", u"?": u"?", u"!": u"!"}, spit=",。?!“”")
特别注意:引号在英语体系中引号是不区分前引号和后引号。