Python3 中一串非英文字符的正确长度
Correct length of a string of non-English characters in Python3
我在一个文件中得到了一串希伯来字符(和其他一些阿拉伯字符。我都不认识)
阿拉伯语
当我从 Python3
中的文件加载此字符串时
fin = open("filename")
x = next(fin).strip()
x
的长度好像是5
>>> len(x)
5
它的unicode utf-8编码是
>>> x.encode("utf-8")
b'\xd7\xa6\xd7\x95\xd6\xb9\xd7\xa8\xe2\x80\x8e'
但是在浏览器中,很明显这些希伯来字符的长度是3。
如何正确获取长度?为什么会这样?
我知道 Python 3 默认是 unicode 所以我没想到会有这样的问题。
您是否尝试过 io
库?
>>> import io
>>> with io.open('text.txt', mode="r", encoding="utf-8") as f:
x = f.read()
>>> print(len(x))
你也可以试试codecs
:
>>> import codecs
>>> with codecs.open('text.txt', 'r', 'utf-8') as f:
x = f.read()
>>> print(len(x))
原因是包含的文本包含控制字符 \u200e
,它是用作 Left-to-right 标记的不可见字符(通常在混合多种语言时使用,以在 Left-to 之间划界-右和从右到左)。此外,它还包括元音 "character"(第二个字符上方的小点显示它的发音)。
例如,如果将 LTR 标记替换为空字符串,则长度为 4:
>> x = 'צוֹר'
>> x
'צוֹר\u200e' # note the control character escape sequence
>> print(len(x))
5
>> print(len(x.replace('\u200e', ''))
4
如果你只想要严格的字母字符和 space 个字符的长度,你可以对所有非 space 非单词字符执行类似 re.sub
的操作:
>> print(len(re.sub('[^\w\s]', '', x)))
3
Unicode 字符有不同的类别。在你的情况下:
>>> import unicodedata
>>> s = b'\xd7\xa6\xd7\x95\xd6\xb9\xd7\xa8\xe2\x80\x8e'.decode("utf-8")
>>> list(unicodedata.category(c) for c in s)
['Lo', 'Lo', 'Mn', 'Lo', 'Cf']
Lo
:字母、其他(不是大写、小写等)。这些是 "real" 个字符
Mn
:标记,非间距。这是与前一个字符组合的某种重音字符
Cf
:控件,格式。这里它切换回从左到右的写入方向
打开utf-8编码的文件。
fin = open('filename','r',encoding='utf-8')
或
with open('filename','r',encoding='utf-8') as fin:
for line1 in fin:
print(len(line1.strip()))
我在一个文件中得到了一串希伯来字符(和其他一些阿拉伯字符。我都不认识)
阿拉伯语
当我从 Python3
中的文件加载此字符串时fin = open("filename")
x = next(fin).strip()
x
的长度好像是5
>>> len(x)
5
它的unicode utf-8编码是
>>> x.encode("utf-8")
b'\xd7\xa6\xd7\x95\xd6\xb9\xd7\xa8\xe2\x80\x8e'
但是在浏览器中,很明显这些希伯来字符的长度是3。
如何正确获取长度?为什么会这样?
我知道 Python 3 默认是 unicode 所以我没想到会有这样的问题。
您是否尝试过 io
库?
>>> import io
>>> with io.open('text.txt', mode="r", encoding="utf-8") as f:
x = f.read()
>>> print(len(x))
你也可以试试codecs
:
>>> import codecs
>>> with codecs.open('text.txt', 'r', 'utf-8') as f:
x = f.read()
>>> print(len(x))
原因是包含的文本包含控制字符 \u200e
,它是用作 Left-to-right 标记的不可见字符(通常在混合多种语言时使用,以在 Left-to 之间划界-右和从右到左)。此外,它还包括元音 "character"(第二个字符上方的小点显示它的发音)。
例如,如果将 LTR 标记替换为空字符串,则长度为 4:
>> x = 'צוֹר'
>> x
'צוֹר\u200e' # note the control character escape sequence
>> print(len(x))
5
>> print(len(x.replace('\u200e', ''))
4
如果你只想要严格的字母字符和 space 个字符的长度,你可以对所有非 space 非单词字符执行类似 re.sub
的操作:
>> print(len(re.sub('[^\w\s]', '', x)))
3
Unicode 字符有不同的类别。在你的情况下:
>>> import unicodedata
>>> s = b'\xd7\xa6\xd7\x95\xd6\xb9\xd7\xa8\xe2\x80\x8e'.decode("utf-8")
>>> list(unicodedata.category(c) for c in s)
['Lo', 'Lo', 'Mn', 'Lo', 'Cf']
Lo
:字母、其他(不是大写、小写等)。这些是 "real" 个字符Mn
:标记,非间距。这是与前一个字符组合的某种重音字符Cf
:控件,格式。这里它切换回从左到右的写入方向
打开utf-8编码的文件。
fin = open('filename','r',encoding='utf-8')
或
with open('filename','r',encoding='utf-8') as fin:
for line1 in fin:
print(len(line1.strip()))