Python 全形轉半形

一隻勤奮愛思考的豬發表於2018-08-01

參考:https://blog.csdn.net/ljp1919/article/details/68925023

背景:
在做日文文字的處理時候,統一半全形字元。
分析:
說明:
全形字元unicode編碼從65281~65374 (十六進位制 0xFF01 ~ 0xFF5E)
半形字元unicode編碼從33~126 (十六進位制 0x21~ 0x7E)
特例:
空格比較特殊,全形為 12288(0x3000),半形為 32(0x20)
除空格外,全形/半形按unicode編碼排序在順序上是對應的(半形 + 0xfee0= 全形),所以可以直接通過用+-法來處理非空格資料,對空格單獨處理。

程式碼

# -*- coding: utf-8 -*-
__author__ = 'jason'

'''
功能:
    全形轉為半形


注:
1. 中文文字永遠是全形,只有英文字母、數字鍵、符號鍵才有全形半形的概念,一個字母或數字佔一個漢字的位置叫全形,佔半個漢字的位置叫半形。
2. 引號在中英文、全半形情況下是不同的

chr()函式用一個範圍在range(256)內的(就是0~255)整數作引數,返回一個對應的字元。
unichr()跟它一樣,只不過返回的是Unicode字元。
ord()函式是chr()函式(對於8位的ASCII字串)或unichr()函式(對於Unicode物件)的配對函式,它以一個字元(長度為1的字串)作為引數,返回對應的ASCII數值,或者Unicode數值。


0x3000: u' ', 0x2212: u'-'
'''
def FullToHalf(mystring):
    n = []
    s = mystring.decode('utf-8')
    for char in s:
        num = ord(char)
        if num == 0x3000:
            num = 32
        elif 0xFF01 <= num <= 0xFF5E:
            num -= 0xfee0
        num = unichr(num)
        n.append(num)
    return ''.join(n)

teststring = "abc-+--ABC123你好世界,。!、"
resu = FullToHalf(teststring)
print "原始字串:\n%s" % (teststring)
resu = resu.encode('utf8')
print "轉為半形後的字串:\n%s" % resu

#對於減號或者破折號的處理
a_half = u'-'#半形減號---−
print "半形減號unicode值=%#x" % (ord(a_half))
a_full = u"-"#全形減號--−
print "全形減號unicode值=%#x" % ord(a_full)
print "全形減號:\n%s" % unichr(ord(a_full)).encode('utf-8')#全形減號
print "半形減號1:\n%s" % unichr(ord(a_half)).encode('utf-8')#半形減號,0x2d
print "半形減號2:\n%s" % unichr(0x2212).encode('utf-8')#半形減號,0x2212,其實這個符號並不在半形範圍內
chazhia_b = ord(a_full) - 0x2212
new_ban_jiao = ord(a_full)-0xfee0#ascii=45,其實是減號/破折號
print "減號全形和半形差值=%#x, 通過將全形減去0xfee0獲取的半形:%s" % (chazhia_b, unichr(new_ban_jiao).encode('utf-8'))
#其實仔細觀看,通過減法獲得到的減號和原生半形減號是不同的。

quan_a = u'a'
ban_a = u'a'
diff_a = ord(quan_a)-ord(ban_a)
print "quan_a=%#x,ban_b=%#x,diff_a=%#x" % (ord(quan_a),ord(ban_a),diff_a)
chazhi1 = ord(quan_a)-0xfee0
print "new_ban_a=%s" % (unichr(ord(quan_a)-diff_a))

結果

原始字串:
abc-+--ABC123你好世界,。!、
轉為半形後的字串:
abc-+--ABC123你好世界,。!、
半形減號unicode值=0x2d
全形減號unicode值=0xff0d
全形減號:
-
半形減號1:
-
半形減號2:
−
減號全形和半形差值=0xdcfb, 通過將全形減去0xfee0獲取的半形:-
quan_a=0xff41,ban_b=0x61,diff_a=0xfee0
new_ban_a=a
# def strQ2B(ustring):
#     """全形轉半形"""
#     rstring = ""
#     for uchar in ustring:
#         inside_code=ord(uchar)
#         if inside_code == 12288:                              #全形空格直接轉換
#             inside_code = 32
#         elif (inside_code >= 65281 and inside_code <= 65374): #全形字元(除空格)根據關係轉化
#             inside_code -= 65248
#         rstring += unichr(inside_code)
#     return rstring
#
# def p(s):
#     s1 = strQ2B(s)
#     p = re.compile('[()]',re.S)
#     s1 = p.sub('',s1)
#     return s1
# num = u'你好###@;,【09[(8)]() [] [(88)]7[6]【5】(綠泡泡)【 × & …… + + 19.88萬 - 哈哈哈'
# print(p(num))
# #你好###@;,【098765綠泡泡【 × & …… + + 19.88萬 - 哈哈哈

相關文章