我有一个Python Unicode字符串。我想确保它只包含罗马字母(A到Z)中的字母,以及欧洲字母表中常见的字母,例如ß,ü,ø,é,à和î。 不应包含其他字母(中文,日文,韩文,阿拉伯文,西里尔文,希伯来文等)中的字符。这样做的最佳方式是什么?
目前我正在使用这段代码,但我不知道这是否是最佳方式:
def only_roman_chars(s):
try:
s.encode("iso-8859-1")
return True
except UnicodeDecodeError:
return False
(我正在使用Python 2.5。我也在Django中这样做,所以如果Django框架碰巧有办法处理这样的字符串,我可以使用该功能 - 我没有遇到过这样的事情,但是。)
答案 0 :(得分:31)
import unicodedata as ud
latin_letters= {}
def is_latin(uchr):
try: return latin_letters[uchr]
except KeyError:
return latin_letters.setdefault(uchr, 'LATIN' in ud.name(uchr))
def only_roman_chars(unistr):
return all(is_latin(uchr)
for uchr in unistr
if uchr.isalpha()) # isalpha suggested by John Machin
>>> only_roman_chars(u"ελληνικά means greek")
False
>>> only_roman_chars(u"frappé")
True
>>> only_roman_chars(u"hôtel lœwe")
True
>>> only_roman_chars(u"123 ångstrom ð áß")
True
>>> only_roman_chars(u"russian: гага")
False
答案 1 :(得分:26)
@tzot的最佳答案很棒,但IMO应该有一个适用于所有脚本的库。 So, I made one(严重依据这个答案)。
pip install alphabet-detector
然后直接使用它:
from alphabet_detector import AlphabetDetector
ad = AlphabetDetector()
ad.only_alphabet_chars(u"ελληνικά means greek", "LATIN") #False
ad.only_alphabet_chars(u"ελληνικά", "GREEK") #True
ad.only_alphabet_chars(u'سماوي يدور', 'ARABIC')
ad.only_alphabet_chars(u'שלום', 'HEBREW')
ad.only_alphabet_chars(u"frappé", "LATIN") #True
ad.only_alphabet_chars(u"hôtel lœwe 67", "LATIN") #True
ad.only_alphabet_chars(u"det forårsaker første", "LATIN") #True
ad.only_alphabet_chars(u"Cyrillic and кириллический", "LATIN") #False
ad.only_alphabet_chars(u"кириллический", "CYRILLIC") #True
此外,主要语言的一些便利方法:
ad.is_cyrillic(u"Поиск") #True
ad.is_latin(u"howdy") #True
ad.is_cjk(u"hi") #False
ad.is_cjk(u'汉字') #True
答案 2 :(得分:1)
对于你说你想做的事,你的方法是正确的。如果您在Windows上运行,我建议您使用cp1252
而不是iso-8859-1
。您也可以允许cp1250
- 这将取消东欧国家,如波兰,捷克共和国,斯洛伐克,罗马尼亚,斯洛文尼亚,匈牙利,克罗地亚等,其中字母表是拉丁语。其他cp125x将包括土耳其语和马耳他语......
您可能还想考虑从西里尔语到拉丁语的转录;据我所知,有几个系统,其中一个系统可能得到万国邮联(万国邮政联盟)的认可。
我对你的评论有点兴趣“我们的运输部门不想用例如中文地址填写标签”......三个问题:(1)你的意思是“国家X的地址“或”用X-ese字符写的地址“(2)你的系统打印标签会不会更好? (3)如果订单未通过测试,订单会如何发货?
答案 3 :(得分:1)
检查ISO-8559-1会错过合理的西方字符,如'œ'和'€'。解决方案取决于您如何定义“西方”,以及您希望如何处理非字母。这是一种方法:
import unicodedata
def is_permitted_char(char):
cat = unicodedata.category(char)[0]
if cat == 'L': # Letter
return 'LATIN' in unicodedata.name(char, '').split()
elif cat == 'N': # Number
# Only DIGIT ZERO - DIGIT NINE are allowed
return '0' <= char <= '9'
elif cat in ('S', 'P', 'Z'): # Symbol, Punctuation, or Space
return True
else:
return False
def is_valid(text):
return all(is_permitted_char(c) for c in text)
答案 4 :(得分:1)
标准string
软件包包含所有Latin
个字母numbers
和symbols
。您可以从文本中删除这些值,如果还有剩余,则不是拉丁字符。我做到了:
In [1]: from string import printable
In [2]: def is_latin(text):
...: return not bool(set(text) - set(printable))
...:
In [3]: is_latin('Hradec Králové District,,Czech Republic,')
Out[3]: False
In [4]: is_latin('Hradec Krlov District,,Czech Republic,')
Out[4]: True
我无法检查所有非拉丁字符,如果有人可以这样做,请告诉我。谢谢。
答案 5 :(得分:0)
检查django.template.defaultfilters.slugify
import unicodedata
value = unicodedata.normalize('NFKD', value).encode('ascii', 'ignore')
是您正在寻找的,然后您可以将结果字符串与原始
进行比较答案 6 :(得分:0)
如果你是django用户,也许会这样做?
from django.template.defaultfilters import slugify
def justroman(s):
return len(slugify(s)) == len(s)
答案 7 :(得分:0)
使用内置的 unicodedata 库简单地回答 tzot,这似乎对我有用:
import unicodedata as ud
def is_latin(word):
return all(['LATIN' in ud.name(c) for c in word])