Python字符串字面量转换为正则表达式对象

3

我有一个返回字符串"r'^A Plat'"的函数,它被写入了一个文本文件中。

get_Pat(file)
    #process text file and now returns "r'^A Plat'"

最初,我将其硬编码在代码中。

pat = r'^A Plat'
use(pat)

现在

pat = get_Pat(file)
use(pat)

但是它在抱怨,我猜它是字符串而不是正则表达式对象。

我已经尝试过:

re.escape(get_Pat(file))

并且。
re.compile(get_Pat(file))

但是它们都不起作用。

如何将字符串文字转换为正则表达式对象?

r'^A Plat'是否等同于简单的re.compile("A Plat")?也许这是一个愚蠢的问题。

如果是use("^A Plat'"),那么它会起作用。
如果是use("r'^A Plat'"),则不起作用 <--- 这是get_Pat(file)输出的内容

我想我的任务就是将字符串r'^A Plat'转换为^A Plat。
但我觉得这只是一个廉价的hack。


@aelon 请看我的修改。我认为它提供了解决方案。 - eyquem
“r'^A Plat'”是不是等同于“re.compile("A Plat")”?不是的;它们之间没有任何关系。前缀r并不代表“正则表达式”或其他任何意思。这里存在多个误解。 - Karl Knechtel
4个回答

2

r'^A Plat''^A Plat'相同,只是不带有rr代表的是原始(raw),而不是正则表达式。它允许你编写带有特殊字符(如\)的字符串,而无需对它们进行转义。

>>> r'^A Plat'
'^A Plat'
>>> r'/ is slash, \ is backslash'
'/ is slash, \\ is backslash'
>>> r'write \t for tab, \n for newline, \" for double quote'
'write \\t for tab, \\n for newline, \\" for double quote'

当编写正则表达式时,原始字符串通常用于包含需要转义的反斜杠。然而,r并没有创建正则表达式对象。

来自Python手册

§ 2.4.1. 字符串字面量

字符串字面量可以选择以字母 'r''R' 为前缀;这样的字符串称为 原始字符串 并使用不同的规则解释反斜杠转义序列。

...

除非有 'r''R' 前缀,否则字符串中的转义序列将根据类似于标准C使用的规则进行解释。


如果他使用了 re.compile(get_Pat(file)) 并且返回的是原始字符串,那么它应该可以正常工作,所以我不认为这是问题的原因。 - Noelkd
啊,我明白了。所以我想re不知道如何处理带有原始关键字的字符串,只是将其视为字符串的一部分。 - ealeon

2

不确定你所说的“它们都无法工作”是什么意思,但re.compile()就是你要找的:

>>> def getPat():
...     return r'^A Plat'
...
...
>>> getPat()
'^A Plat'
>>> reObj = re.compile(getPat())
>>> reObj
<_sre.SRE_Pattern object at 0x16cfa18>
>>> reObj.match("A Plat")
<_sre.SRE_Match object at 0x16c3058>
>>> reObj.match("foo")

编辑:

你可以使用以下代码去除返回结果中多余的r' '

>>> s = "r'^A Plat'"
>>> s = s[1:].strip("'")
>>> s
'^A Plat'

据我理解代码中的注释,他返回的是"r'^A Plat'"而不是r'^A Plat'。正如你指出的那样,使用原始字符串编译没有问题。 - Noelkd
我猜这个问题的表述有点令人困惑。 - bgporter
1
我同意,我认为这是一个x/y问题,原始字符串只是一个误导。可能是错误的,因为它仍然不明确。 - Noelkd
该函数返回的是"r'A Plat'",不仅仅是'^A Plat'。 - ealeon

2

Do

from ast import literal_eval
pat = literal_eval(get_Pat(file))

编辑

aelon,

正如你在评论中所写,你无法导入literal_eval(),因此我上面的解决方案对你来说是无用的。除此之外,尽管表达了有趣的信息,其他答案并没有提出另一种解决方案。
因此,我提出了一种新的解决方案,不使用literal_eval()

import re

detect = re.compile("r(['\"])(.*?)\\1[ \t]*$")

with open('your_file.txt') as f:
    pat = f.readline()

if detect.match(pat):
    r = re.compile(detect.match(pat).group(2))
else:
    r = re.compile(pat)

解释:

.

假设在 *your_file* 的第一行写有字符序列 r'^六点钟\n吉姆'

打开并读取 *your_file* 的第一行会创建一个对象pat
- 它的类型在Python 2中为<type 'str'>,在Python 3中为<class 'str'>
- 它的表示为"r'^六点钟\n吉姆'"
- 它的值为r'^六点钟\n吉姆',也就是由字符r'^\'组成
如果文件中有第二行,则末尾可能还有“字符”\n。此外,在文件中写入r'^六点钟\n吉姆'和其行的末尾之间可能还有空格或制表符。因此,我使用[ \t]*$关闭了正则表达式模式以定义detect
因此,我们可能会在感兴趣的字符后获得可能的额外空格、制表符和换行符,如果我们执行print tuple(pat),我们将获得例如:

('r', "'", '^', 'S', 'i', 'x', ' ', 'o', '\\', "'", 'c', 'l', 'o', 'c', 'k', '\\', 'n', 'J', 'i', 'm', "'", ' ', ' ', ' ', '\t', '\n')

现在,让我们考虑使用表达式detect.match(pat).group(2)得到的对象。
它的值为^Six o\'clock\nJim,由18个字符组成,其中\'以及n是其中的三个不同字符,其中没有一个转义字符\'和一个转义字符\n
这个值与通过编写指令rawS = r'^Six o\'clock\nJim'获得的名称为rawS的对象的值完全相同。
然后,我们可以通过直接编写r = re.compile(detect.match(pat).group(2))来获得其模式以r'....'形式写入文件的正则表达式。
在我的示例中,序列\'\n是文件中写的字符序列中唯一的序列。但是,所有前面的内容都适用于语言中的任何转义序列

换句话说,我们无需考虑与表达式r'^Six o\'clock\nJim'相同的函数,从值为r'^Six o\'clock\nJim'的字符串"r'^Six o\'clock\nJim'"的STRING中获得该函数,
我们直接将detect.match(pat).group(2)捕获的字符串的值作为r'^Six o\'clock\nJim'的结果。

在Python 2中,类型<type 'str'>是一组有限的字符类型。
它是以模式'r'和模式'rb'打开的文件的读取内容的类型。

在Python 3中,类型<class 'str'>涵盖了unicode字符。
但与Python 3相反,以模式'r'打开的文件的读取内容是类型<type 'str'>
而如果使用模式'rb'打开文件,则其类型为<class 'bytes'>

然后,我认为上面的代码在Python 3中与Python 2一样有效,因此应以模式'r'打开该文件。

如果文件应以'rb'打开,则正则表达式模式应更改为b"r(['\"])(.*?)\\1[ \t]*\r?\n"

.

AFAIHU


2
我认为这正是原帖作者想要的。但如果您能解释一下为什么,那么这将是一个更好的答案。 - SethMMorton
1
@SethMMorton 或许你会对我的编辑中的解释感兴趣。 - eyquem
1
我希望我能再点赞一次。 - SethMMorton

1
根据您的get_pat函数中的注释,它返回:

"r'^A Plat'"

这不是您认为的结果。
>>> x = re.compile("r'^A Plat'")
>>> y = "A Plat wins"
>>> x.findall(y)
[]
>>> x = re.compile("^A Plat")
>>> x.findall(y)
['A Plat']
>>>

所以你使用的正则表达式不是r'^A Plat',而是"r'^A Plat'",r'^A Plat'是可以的:

>>> x = re.compile(r'^A Plat')
>>> x.findall(y)
['A Plat']

要解决这个问题,我需要了解您最初如何获取字符串“r'^A Plat'”。

是的。问题在于我的函数返回了字符串对象“r'^A Plat'”,所以我想我可以通过将其转换为“^A Plat”来解决它。 - ealeon
如果你必须使用该函数返回的字符串,你应该查看eyquems的答案。 - Noelkd
没有 ast 导入的访问权限。 - ealeon
如果您发布了get_pat()的代码,可能会有简单的方法来解决您的问题。 - Noelkd
@Noelkd 我已经编辑了我的答案,其中包含我认为是有效解决方案的内容。 - eyquem

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