在Python中检测包含非英文字符的字符串

72

我有一些字符串,其中混合了英文和非英文字符。例如:

w='_1991_اف_جي2'

如何使用正则表达式或任何其他快速方法在Python中识别这些字符串类型?

我不希望逐个与字母列表比较字符串的字母,而是希望以一次快速的方式完成。


1
也许可以使用ASCII范围,因为我相信ASCII只包含0-255的英文字符。 - jgr208
你能告诉我如何在Python中实现吗? - TJ1
@TJ1 你使用的是哪个Python版本? - thefourtheye
请查看 这个回答。别忘了给那个回答和问题点赞 :) - user378704
6个回答

115

你可以检查字符串是否只能由ASCII字符(拉丁字母+一些其他字符)编码。如果不能编码,则它具有来自其他字母表的字符。

请注意注释# -*- coding: ....。它应该在Python文件的顶部(否则你可能会收到关于编码的错误)。

# -*- coding: utf-8 -*-
def isEnglish(s):
    try:
        s.encode(encoding='utf-8').decode('ascii')
    except UnicodeDecodeError:
        return False
    else:
        return True

assert not isEnglish('slabiky, ale liší se podle významu')
assert isEnglish('English')
assert not isEnglish('ގެ ފުރަތަމަ ދެ އަކުރު ކަ')
assert not isEnglish('how about this one : 通 asfަ')
assert isEnglish('?fd4))45s&')

11
感谢您的回答。在Python 3中,您所说的方法不能正常工作,但我使用了您建议的方法,将s.decode('ascii')替换为s.encode('ascii'),并将UnicodeDecodeError替换为UnicodeEnecodeError,然后它就起作用了。 - TJ1
1
我确实使用Python2来测试我的代码。感谢您为Python3改进了解决方案。 - Salvador Dali
3
我已经编辑过这个答案,可以在Python 2和3中使用。 - Jonas Adler
3
@TJ1,你的Python3方法是正确的,只是有一个拼写错误——应该是UnicodeEncodeError - tsveti_iko

47

我认为这是最简单的解决方案:

def isEnglish(s):
  return s.isascii()

print(isEnglish("Test"))
print(isEnglish("_1991_اف_جي2"))

Output:
True
False

7
isascii 函数是在 Python 3.7 版本中引入的。因此,要使用该函数,你必须拥有 Python 3.7 或更高版本。 - Kaushal

22

如果你使用字符串(而不是Unicode对象),你可以使用翻译来清理它,并使用 isalnum() 进行检查,这比抛出异常更好:

import string

def isEnglish(s):
    return s.translate(None, string.punctuation).isalnum()


print isEnglish('slabiky, ale liší se podle významu')
print isEnglish('English')
print isEnglish('ގެ ފުރަތަމަ ދެ އަކުރު ކަ')
print isEnglish('how about this one : 通 asfަ')
print isEnglish('?fd4))45s&')
print isEnglish('Текст на русском')

> False
> True
> False
> False
> True
> False

还可以使用这个函数从字符串中过滤掉非ASCII字符:

ascii = set(string.printable)   

def remove_non_ascii(s):
    return filter(lambda x: x in ascii, s)


remove_non_ascii('slabiky, ale liší se podle významu')
> slabiky, ale li se podle vznamu

2
嗨,虽然这个解决方案看起来很好(我想尽可能避免异常),但它并不能识别所有的英文字符。甚至连“空格”也无法识别。 - jottbe

7

我相信这个函数的运行时间非常短,因为它一旦遇到一个非拉丁字母字符就会停止。此外,它使用生成器来更好地利用内存。

import string

def has_only_latin_letters(name):
    char_set = string.ascii_letters
    return all((True if x in char_set else False for x in name))

>>> has_only_latin_letters('_1991_اف_جي2')
False
>>> has_only_latin_letters('bla bla')
True
>>> has_only_latin_letters('blä blä')
False
>>> has_only_latin_letters('저주중앙초등학교')
False
>>> has_only_latin_letters('also a string with numbers and punctuation 1, 2, 4')
True

您还可以使用不同的字符集:

>>> string.ascii_letters
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'

>>> string.ascii_lowercase
'abcdefghijklmnopqrstuvwxyz'

>>> string.ascii_uppercase
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'

>>> string.punctuation
'!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'

>>> string.digits
'0123456789'

>>> string.digits + string.lowercase
'0123456789abcdefghijklmnopqrstuvwxyz'    

>>> string.printable
'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%& 
\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c'

要添加拉丁文重音字母,您可以参考此帖子


6
import re

english_check = re.compile(r'[a-z]')

if english_check.match(w):
    print "english",w
else:
    print "other:",w

6
像 "naïve" 或 "cliché" 这样的词怎么处理? - Maximilian Peters
与被接受的答案相反,这也适用于带有重音符号的字符串 :-)(我使用 ['tele', 'tèle', 'τήλε'] 进行了测试,结果为 [True, True, False]。) - Frank

0
w.isidentifier()

您可以在文档中轻松查看该方法:

如果字符串根据语言定义,即标识符和关键字部分是有效的标识符,则返回true。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接