如何在Python中搜索和替换UTF-8特殊字符?

14

我是一个Python初学者,遇到了一个utf-8编码问题。

我有一个utf-8字符串,并且想要用ASCII替换所有的德语umlaut(在德语中,u-umlaut 'ü' 可以被重写为“ue”)。

u-umlaut具有Unicode编码点252,所以我尝试了以下代码:

>>> str = unichr(252) + 'ber'
>>> print repr(str)
u'\xfcber'
>>> print repr(str).replace(unichr(252), 'ue')
u'\xfcber'

我原本期望最后的字符串是u'ueber'

我的最终目标是将文件中所有的u-umlauts替换成'ue':

import sys
import codecs      
f = codecs.open(sys.argv[1],encoding='utf-8')
for line in f: 
    print repr(line).replace(unichr(252), 'ue')

感谢您的帮助!(我正在使用Python 2.3版本。)


2
请注意,Unicode标准还定义了组合字符。因此,ü也可以用Unicode序列U+0075 U+0308表示。 - elmuerte
4个回答

15

我将定义一个特殊字符的字典(我想要进行映射),然后使用translate方法。

line = 'Ich möchte die Qualität des Produkts überprüfen, bevor ich es kaufe.'

special_char_map = {ord('ä'):'ae', ord('ü'):'ue', ord('ö'):'oe', ord('ß'):'ss'}
print(line.translate(special_char_map))

您将获得以下结果:
Ich moechte die Qualitaet des Produkts ueberpruefen, bevor ich es kaufe.

2
@Pontis 没有人使用 sz 代替 ß,人们只使用 ss - dmuensterer
1
你忘记了大写的umlauts,比如“Ä”,“Ö”,“Ü”。也许需要更新你本来超级整洁的解决方案。 - Ron

11

我认为更简单更清晰的方法是直接使用'ü'的Unicode表示,而不是使用unichr(252)。

>>> s = u'über'
>>> s.replace(u'ü', 'ue')
u'ueber'

不需要使用repr,因为这将打印字符串的“Python表示”,你只需要呈现可读的字符串。

如果文件中还没有,请在.py文件开头包含以下行,以指定文件的编码方式。

#-*- coding: UTF-8 -*-
添加:当然,声明的编码必须与文件的编码相同。请检查一下,因为可能会出现一些问题(例如,在Windows上使用Eclipse时,它默认将文件写成cp1252格式)。另外,它应该是系统的相同编码,可以是utf-8、latin-1或其他编码。

此外,不要将 str 作为变量的定义,因为它是Python库的一部分。以后可能会遇到问题。

(我在尝试Python 2.6,我认为在Python 2.3中结果是相同的)


一个重要的点:实际上要将源文件保存在编码声明中声明的编码中。很多人会忘记这一点。 - Mark Tolonen
你必须确保能够以UTF-8格式编辑此文件。例如,如果整个系统都设置为Latin-1,则无论文件中的编码声明如何,它都无法正常工作。这意味着,如果无法保证使用UTF-8,则最好使用原始的unichr方法。 - Jürgen A. Erhard
我根据评论添加了一些信息。 @mark:好观点,我因此在Eclipse上遇到了一些问题。 @jae 我认为最好的方法是声明一致的编码,然后将字符声明为u'ü'。在代码中声明它作为Unicode编号似乎相当令人困惑。我同意,在奇怪的情况下这可能是不可避免的,但是根据我的经验,通常很容易使用适当的编码。 - Khelben

10

repr(str) 返回一个带引号的版本的 str,当打印出来时,会得到一个可以作为 Python 代码输入以获取该字符串的字符串。因此,它是一个真正包含 \xfcber 的字符串,而不是一个包含 über 的字符串。

你可以使用 str.replace(unichr(252), 'ue')ü 替换为 ue

虽然我认为您不需要这样做,但如果您需要获得该结果的带引号版本,可以将整个表达式包装在 repr 中:

repr(str.replace(unichr(252), 'ue'))

9

您可以避免所有源文件编码问题及其问题。使用Unicode名称,那么您正在做什么的呼声非常明显,代码可以在任何地方阅读和修改。

我不知道有哪种语言只有小写带两个点的u字母,也就是u-umlaut-aka-diaeresis,因此我添加了循环遍历翻译表的代码,假定您需要它。

# coding: ascii

translations = (
    (u'\N{LATIN SMALL LETTER U WITH DIAERESIS}', u'ue'),
    (u'\N{LATIN SMALL LETTER O WITH DIAERESIS}', u'oe'),
    # et cetera
    )

test = u'M\N{LATIN SMALL LETTER O WITH DIAERESIS}ller von M\N{LATIN SMALL LETTER U WITH DIAERESIS}nchen'

out = test
for from_str, to_str in translations:
    out = out.replace(from_str, to_str)
print out

输出:

Moeller von Muenchen

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