日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

rhel 8.2不识别unicode_Unicode的文本处理二三事

發布時間:2025/4/16 编程问答 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 rhel 8.2不识别unicode_Unicode的文本处理二三事 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本文不對unicode進行科普式的宣講,主要針對其在文本處理過程中的一些有趣應用進行記錄和剖析。

0x01. 前言

在日常工作的文本處理過程中,經常會遇到一些利用unicode特性對文本進行處理的技巧。在這篇文章中則主要對其進行一些匯總和剖析。在開始之前,這里對 unicode 一些鮮為人知的概念做一些介紹。

大部分時候,我們都會只認為Unicode只是對字符的一個數字編碼,在Python內部,我們可以通過這樣的方式,查看一個文本的 unicode 編碼:

a = "母" a.encode("raw_unicode_escape") # b'u2e9f'

但實際上,一個unicode除了其 codepoint 之外,還有很多特殊的屬性,而這些屬性在很多的NLP處理任務的過程中起到幫助的作用。如下圖:

unicode的其他屬性

在這里,我推薦使用這個站點來查詢unicode的相關屬性。從上圖可以看出,一個unicode還具備以下常用的屬性:

  • Name: 每個Unicode會有一個獨特的名字,后面我們會展示一個根據名字前綴來識別unicode屬于哪一種語言的技巧。
  • Block: 一個連續的編碼范圍,具體可以參考:Wikipedia - Unicode block
  • Plane: 具體可以參考:Wikipedia - Plane (Unicode)
  • Script: 每個文字的書寫體系,具體可以參考:Wikipedia - Script(Unicode)。
  • Category: 類別,待會會詳細介紹。

0x02. Unicode Range

我們都知道unicode利用一個數字來表示每個字符。而實際上,每個書寫語言(script)所涉及的文字,都有其獨特的unicode范圍。因此最直接的一個應用就是利用 unicode range 來判定一個字符 or 文本屬于哪一種語言。

在開始之前,我先推薦一個站點:Code Chars。這個站點按照不用的書寫語言和地域進行分類,列舉出每個語言的unicode range。如下圖綠框,其中中文script的名字叫做 Unihan。

Code Chars:不同語言的unicode-range

在上面站點可以查詢到,漢字(Han scirpt)包含以下的block,而每個block的 block-range 可以表示為:

  • CJK Unified Ideographs: U+4E00–U+9FEF
  • CJK Unified Ideographs Extension A: U+3400–U+4DB5
  • CJK Unified Ideographs Extension B: U+20000–U+2A6D6
  • CJK Unified Ideographs Extension C: U+2A700–U+2B734
  • CJK Unified Ideographs Extension D: U+2B740–U+2B81D
  • CJK Unified Ideographs Extension E: U+2B820–U+2CEA1
  • CJK Unified Ideographs Extension F: U+2CEB0–U+2EBE0

因此,我們可以根據上述的 unicode-range,開開心心的寫一個判定是否為漢字的正則表達式

HAN_SCRIPT_PAT = re.compile(r'[u4E00-u9FEFu3400-u4DB5u20000-u2A6D6u2A700-u2B734'r'u2B740-u2B81Du2D820-u2CEA1u2CEB0-u2EBE0]' )def is_chinese_char(c):return bool(HAN_SCRIPT_PAT.match(c))

然而值得注意的是,這種方法并不算是一種很好的方式。因為不同文字的unicode范圍會有變化。如果只是一次性的搞一波,那也可以考慮一下。

0x03. Unicode 的其他屬性應用

在這一小節,我們主要討論unicode的其他屬性以及 normalize 的問題,主要涉及 Python 中 unicodedata 和 regrex 兩個標準庫。

3.1 字符名字(Name)判斷:

在第一小節中我們提及到,每個unicode字符都有其獨特的名字。在Python中,我們可以通過這樣的方式來獲取某個unicode字符的名字:

import unicodedata text = "中" print(unicodedata.name(text)) # CJK UNIFIED IDEOGRAPH-4E2D

進一步的,我們可以簡單來看下多個unicode的名字特點:從下表可以看到: 對于中文字符,其 Unicode 名字都是以 CJK 開頭; 對于印地語(天成文),其前綴也基本是以 DEVANAGARI 開頭; * 對于表情符號,其名字還包含了表情符號本身的文字描述。這額外的描述也可以在NLP任務過程中作為表情符號的特征進行補充,讓模型能夠更好的理解符號本身。

回到判定字符所屬的語言任務本身,利用Unicode-range判定法會存在范圍變化的問題。那么可以更改為利用名字判斷:

def is_chinese_char(c):return unicodedata.name(c).startswith("CJK")

除了利用名字之外,更加規范的做法應該是直接判斷該unicode的Script屬性(漢字的Script屬于Han)。可惜 unicodedata 這個庫不支持。但是可以用 regrex 庫搞一波:

def is_chinese_char(c):return bool(regrex.match(r"p{script=han}", c))

3.2 字符類別(Category)判斷:

在Unicode中,每個字符還會被賦予上Category的屬性,而這個屬性跟語種是無關的。總體而言,Category一共分為 Letter, Mark, Number, Punctuation, Symbol, Seperator, Other 七大類, 而每個類別下面還有進一步的二級分類。在 Python 中,我們可以利用 unicodedata.category 這個庫來獲取這個屬性;

import unicodedatarst = [] for char in "1a天。 ??":rst.append("{}:{}".format(char, unicodedata.category(char)))print(",".join(rst))# 1:Nd,a:Ll,天:Lo,。:Po, :So,?:So,?:Mn

更詳細的,我們可以來看看所有Category的類型碼和對應信息類別:

二級Category列表,參考[1]

一旦知曉了字符的類別,那么在文本處理過程中就有很多技巧可以應用的上的。例如:

  • 利用類別中P開頭的字符,把標點符號全部篩選出來。
  • 類別N開頭的是數字符號,除了常見的阿拉伯數字,還可以將羅馬數字、其他語種的數字體、帶圓圈的數序序號等也排除出來。
unicodedata.category("?") == 'Nd' # 天成文中的數字2 unicodedata.category("⑩") == 'Nd'
  • 利用類別中C類別的字符,可以把文本中一些不可見的控制字符(如"^V, ^I" 或者zero-width的如u200d等字符)給過濾掉:
import unicodedata text = text.replace("t", " ") return "".join(ch for ch in text if unicodedata.category(ch)[0] != 'C')

在這里,我展示一下 tensor2tensor 中計算 BLEU 分數的時候,用于分詞的函數 bleu_tokenizer:

class UnicodeRegex(object):"""Ad-hoc hack to recognize all punctuation and symbols."""def __init__(self):# 獲取所有的標點符號punctuation = self.property_chars("P")# 標點符號左邊不帶數字self.nondigit_punct_re = re.compile(r"([^d])([" + punctuation + r"])")# 標點符號右邊不帶數字self.punct_nondigit_re = re.compile(r"([" + punctuation + r"])([^d])")# 所有的符號集合self.symbol_re = re.compile("([" + self.property_chars("S") + "])")def property_chars(self, prefix):return "".join(six.unichr(x) for x in range(sys.maxunicode)if unicodedata.category(six.unichr(x)).startswith(prefix))uregex = UnicodeRegex()def bleu_tokenize(string):# 粗暴的分割所有除了前后包含數字的標點符號。string = uregex.nondigit_punct_re.sub(r"1 2 ", string)string = uregex.punct_nondigit_re.sub(r" 1 2", string)# 所有的symbol默認分割string = uregex.symbol_re.sub(r" 1 ", string)return string.split()

3.3 對unicode字符進行normalized:

在某些自然語言處理任務的過程中,會遇到一些神奇的靈異現象。 例如兩個單詞 or 字符用肉眼看是完全一模一樣的,但是在計算機中讀取出來卻表示兩者不相等。進一步的,當我們查看這個item的編碼字符的時候,發現兩者確實也不一樣。那究竟是什么樣的一回事呢??

text_a = "?????" text_b = "??????"print(text_a == text_b) # False print(unicodedata.normalize("NFKD", text_a) == text_b) # True

事實上,在Unicode的編碼中,經常會有一些特殊字符被編碼成多種 Unicode 形式。例如: 字符 U+00C7 (LATIN CAPITAL LETTER C WITH CEDILLA) 也可以被表示為下面列個字符的組合: U+0043 (LATIN CAPITAL LETTER C) 和 字符U+0327 (COMBINING CEDILLA).

這種情況下多發于那些需要包含音調的字符體系中(例如印地語、德語、西班牙語等),如以下字符"?"。Unicode體系中,即可以用Compose(組合)的形式U+00C7來表示這個字符。 也可以使用Decompose(分離)分別存儲字符(U+0043)本身和音調(U+0327)本身。

在上面的印地語中,出現問題的主要是因為字符"?",該字符下有一個小點,表示印地語中的一些音調問題(具體參考 Nuqta)。該字符就擁有 Compose 和 Decompose 兩種Unicode表示方法, 因此才會出現上文中字符不等的例子。

在Python中,我們可以利用 unicodedata.normalize 函數對字符進行標準化。標準化分為兩個方式:

  • unicodedata.normalize("NFKC", text): Normal form Composition: 將所有的文本標準化為 Compose 形式。
  • unicodedata.normalize("NFKD", text): Normal form Decomposition: 將所有的文本標準化為 Decompose 形式。

更標準的寫法,應該為

import unicodedata def strip_accents(s):return ''.join(c for c in unicodedata.normalize('NFD', s)if unicodedata.category(c) != 'Mn')

3.3.1 題外話:

在撰寫本文的時候,我發現了一些外觀長的一模一樣,并且通過normalize方法也無法歸一化的問題。例如:

a = "?" b = "馬"print(a == b) # False print(a.encode("raw_unicode_escape")) # b'u2ee2' print(b.encode("raw_unicode_escape")) # b'u9a6c' print(unicodedata.normalize("NFKD", a) == b) # False print(unicodedata.normalize("NFKC", a) == b) # False

于是我對上述文本中的第一個『馬』進行了一番查詢(正是文章開頭圖片的字符),發現:

  • 第一個馬的Category是一個Symbol,也就是說是一個符號。
  • 第一個馬的Block屬于Radical-Block,查詢了一下,主要是在漢字中用于偏旁作用的。

那么,如果在實際應用中,應該如何對這兩個字符進行歸一化呢??? 目前我也沒有 idea 。。。。。

0x04. Reference:

  • [1]. NLP哪里跑: Unicode相關的一些小知識和工具
  • [2]. Python - Unicodedata

總結

以上是生活随笔為你收集整理的rhel 8.2不识别unicode_Unicode的文本处理二三事的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。