Python:使用re.sub处理编码为&#数字;的ASCII数字

2 投票
3 回答
878 浏览
提问于 2025-04-18 07:11

我有一段文本,里面有一些奇怪的字符。例如,单词 'éxâmplë' 可能会出现。但是它并不是以正常的方式显示,而是像这样 &#130;x&#131;mpl&#137;。幸运的是,这些数字是用 ASCII 编码的,所以我可以用 chr() 来处理。因此,我想把 &#<数字>; 替换成 chr(数字)

我开始使用 re 模块来实现这个功能,但因为我对这个模块不太熟悉,所以不知道该怎么做。下面是我的尝试,但当然,代码在执行 re.sub() 之前就试图把 int() 部分转换成整数,这导致了一个 ValueError。我该怎么正确地做这个呢?

sentence = "This is an &#130;x&#131;mpl&#137;."
chrpatt = "&#([0-9]{3});"
sentence = re.sub(chrpatt, chr(int("\g<1>")), sentence)
print sentence

3 个回答

1

你可以使用可调用参数来处理 sub() 函数:

>>> import re
>>> sentence = "This is an &#130;x&#131;mpl&#137;."
>>> chrpatt = "&#([0-9]{3});"
>>> def rpl(m): return chr(int(m.group(1)))
>>> re.sub(chrpatt, rpl, sentence)
'This is an \x82x\x83mpl\x89.'
>>> print re.sub(chrpatt, rpl, sentence)
This is an éxâmplë.

显然,这些数据是用某种DOS编码格式(437或850)编码的:在我家用的Linux系统上,我需要这样做

>>> print re.sub(chrpatt, lambda m: chr(int(m.group(1))) , sentence).decode("cp437")
This is an éxâmplë.
>>> re.sub(chrpatt, lambda m: chr(int(m.group(1))) , sentence).decode("cp437")
u'This is an \xe9x\xe2mpl\xeb.'

才能得到正确的输出。

这里发生了什么呢?

对于每一个匹配项,给定的函数会接收到一个匹配对象,然后这个函数需要返回一个替换字符串。

所以我们就这样做——从匹配中提取出数字,并按照你建议的步骤进行操作。

3

这里其实不需要用到正则表达式。

有一个专门的库叫做 HTMlParser,可以用来处理这个问题。

举个例子:

>>> import HTMLParser
>>> h = HTMLParser.HTMLParser()
>>> h.unescape("This is an &#130;x&#131;mpl&#137;.")
u'This is an \x82x\x83mpl\x89.'

如果之前没说清楚的话:

>>> chr(130)
'\x82'
>>> chr(131)
'\x83'
>>> chr(137)
'\x89'

别重复造轮子

2

int("\g<1>") 这里会出现一个值错误(ValueError)。int 是用来转换成整数的一个工具。如果你给这个工具一个字符串,它会期待这个字符串能代表一个数字。很明显,字符串 "\g<1>" 看起来并不像是一个数字的表示。

在你的例子中,re.sub 的第二个参数应该是一个函数,这个函数会接收找到的匹配项并对其进行转换。

引用自 Python 文档 https://docs.python.org/3.4/library/re.html#re.sub

re.sub(pattern, repl, string, count=0, flags=0)

...

如果 repl 是一个函数,它会在每次找到不重叠的模式时被调用。这个函数接收一个匹配对象作为参数,并返回替换的字符串。例如:

撰写回答