如何在python中删除转义序列,如'\ xe2'或'\ x0c'

时间:2013-02-18 22:03:03

标签: python regex escaping string-literals

我正在开发一个项目(基于内容的搜索),因为我在Ubuntu中使用'pdftotext'命令行实用程序,它将pdf中的所有文本写入某个文本文件。 但是它也写了子弹,现在当我读取文件来索引每个单词时,它也会得到一些索引的转义序列(比如'\ x01')。我知道它是因为子弹(•)。

我只想要文本,所以有没有办法删除这个转义序列。我做过类似的事情

escape_char = re.compile('\+x[0123456789abcdef]*')
re.sub(escape_char, " ", string)

但这不会删除转义序列

提前致谢。

3 个答案:

答案 0 :(得分:6)

问题是\xXX只是控制角色的表示,而不是角色本身。因此,除非您使用字符串的\x,否则无法与repr字面匹配。

您可以使用字符类删除不可打印的字符:

re.sub(r'[\x00-\x08\x0b\x0c\x0e-\x1f\x7f-\xff]', '', text)

示例:

>>> re.sub(r'[\x00-\x1f\x7f-\xff]', '', ''.join(map(chr, range(256))))
' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~'

答案 1 :(得分:1)

你唯一真正的问题是反斜杠很棘手。在字符串中,可以特别处理反斜杠;例如\t会变成一个标签。由于\+在字符串中并不特殊,因此字符串实际上是您所期望的。然后正则表达式编译器查看它,正则表达式中的\+只是一个普通的+字符。通常+具有特殊含义(“前一个模式的一个或多个实例”),反斜杠会将其转义。

解决方案只是将反斜杠加倍,这使得模式与单个反斜杠匹配。

我将模式放入r'',使其成为“原始字符串”,其中Python单独留下反斜杠。如果你不这样做,Python的字符串解析器会将两个反斜杠转换成一个反斜杠;就像\t变成一个标签一样,\\变成一个反斜杠。因此,使用原始字符串并准确地放置您希望正则表达式编译器看到的内容。

另外,更好的模式是:反斜杠,然后是x,然后是匹配十六进制字符的一个或多个字符类实例。我重写了这个模式。

import re

s = r'+\x01+'
escape_char = re.compile(r'\\x[0123456789abcdef]+')
s = re.sub(escape_char, " ", s)

您可以使用普通字符串,而不是使用原始字符串,只需要非常小心反斜杠。在这种情况下,我们将不得不放四个反斜杠!字符串解析器会将每个加倍的反斜杠转换为单个反斜杠,我们希望正则表达式编译器看到两个反斜杠。使用原始字符串更容易!

此外,您的原始模式将删除零个或多个十六进制数字。我的模式删除了一个或多个。但我认为可能总会有两个十六进制数字,或者可能有Unicode,也许会有四个。你应该弄清楚可以有多少并设置一个模式来确保这一点。这是一个匹配2,3或4个十六进制数字的模式:

escape_char = re.compile(r'\\x[0123456789abcdef]{2,4}')

这里只有两个或恰好四个匹配。我们必须使用竖线来制作两个替代方案,我们需要创建一个带括号的组。我在这里使用了一个不匹配的群组,(?:pattern)而不是(pattern)(其中pattern表示模式,而不是单词pattern)。

escape_char = re.compile(r'\\x(?:[0123456789abcdef]{2,2}|[0123456789abcdef]{4,4})')

这是示例代码。子弹序列后面紧跟着一个1字符,这种模式不管它。

import re

s = r'+\x011+'
pat = re.compile(r'\\x(?:[0123456789abcdef]{2,2}|[0123456789abcdef]{4,4})')
s = pat.sub("@", s)
print("Result: '%s'" % s)

打印:Result: '+@1+'

注意:所有这些都假设您实际上正在尝试匹配反斜杠字符后跟十六进制字符。如果您实际上尝试匹配可能或可能不是“可打印”字符的字符字节值,请使用@nneonneo而不是此答案的答案。

答案 2 :(得分:1)

如果您正在处理8位字符值,则可以通过预先构建一些简单的表来放弃正则表达式,然后使用它们与str.translate()方法联合以删除字符串中的不需要的字符快速而轻松:

import random
import string

allords = [i for i in xrange(256)]
allchars = ''.join(chr(i) for i in allords)
printableords = [ord(ch) for ch in string.printable]
deletechars = ''.join(chr(i) for i in xrange(256) if i not in printableords)

test = ''.join(chr(random.choice(allords)) for _ in xrange(10, 40)) # random string
print test.translate(allchars, deletechars)