如何在正则表达式中使用变量?


235

我想在a variable内部使用regex,该怎么办Python

TEXTO = sys.argv[1]

if re.search(r"\b(?=\w)TEXTO\b(?!\w)", subject, re.IGNORECASE):
    # Successful match
else:
    # Match attempt failed

9
您使用字符串连接
Chris Eberle

Answers:


52

从python 3.6开始,您还可以使用文字字符串插值(“ f-strings”)。在您的特定情况下,解决方案是:

if re.search(rf"\b(?=\w){TEXTO}\b(?!\w)", subject, re.IGNORECASE):
    ...do something

编辑:

既然评论中存在一些有关如何处理特殊字符的问题,我想扩展一下我的答案:

原始字符串('r'):

在正则表达式中处理特殊字符时,您必须了解的主要概念之一是区分字符串文字和正则表达式本身。这是很好的解释在这里

简而言之:

假设您要匹配字符串\b之后,而不是查找单词边界。你必须写:TEXTO\boundary

TEXTO = "Var"
subject = r"Var\boundary"

if re.search(rf"\b(?=\w){TEXTO}\\boundary(?!\w)", subject, re.IGNORECASE):
    print("match")

这仅起作用,因为我们使用的是原始字符串(正则表达式以'r'开头),否则我们必须在正则表达式中写入“ \\\\ boundary”(四个反斜杠)。另外,如果没有'\ r',\ b'将不再转换为单词边界,而是转换为退格键!

重新转义

基本上在任何特殊字符的前面放置一个空格。因此,如果您希望TEXTO中有特殊字符,则需要编写:

if re.search(rf"\b(?=\w){re.escape(TEXTO)}\b(?!\w)", subject, re.IGNORECASE):
    print("match")

注:对于任何版本> = 3.7蟒:!"%',/:;<=>@,和`都没有逃脱。仅对正则表达式中具有含义的特殊字符进行转义。_因为Python 3.3没有逃脱。(送。这里

大括号:

如果要在使用f字符串的正则表达式中使用量词,则必须使用双花括号。假设您要匹配TEXTO,然后再精确匹配2位数字:

if re.search(rf"\b(?=\w){re.escape(TEXTO)}\d{{2}}\b(?!\w)", subject, re.IGNORECASE):
    print("match")

2
截至2020年,这是在正则表达式中使用变量的最简单,最Python的方式
CONvid19

3
这绝对是一个WOW
詹森·目标

2
有人可以解释“RF”在这里的意义
戒雷迪

1
@HarshaReddy:'r':此字符串是原始字符串:如果不使用它,则'\ b'将转换为退格字符(docs.python.org/3/howto/regex.html#more-模式功率)。'f'告诉python这是一个'f-string',s。上方的链接,并允许您将变量写入花括号中
airborne

2
如何用f字符串写量词:(fr"foo{{1,5}}"大括号加倍)
PunchyRascal

281

您必须将正则表达式构建为字符串:

TEXTO = sys.argv[1]
my_regex = r"\b(?=\w)" + re.escape(TEXTO) + r"\b(?!\w)"

if re.search(my_regex, subject, re.IGNORECASE):
    etc.

请注意使用,re.escape这样如果您的文本中包含特殊字符,则不会这样解释它们。


4
如果您的变量排在第一位怎么办?r'' + foo + 'bar'
deed02392 2013年

r''如果您这样做re.escape(foo),则@ deed02392 并不是必须的,无论如何都应该这样做。实际上,re无论您是否前缀,我都认为将给出的任何内容解释为unicode字符串r
OJFord 2014年

.format()是否可以代替re.escape正常工作,还是需要re.escape()?
Praxiteles

@praxiteles您找到答案了吗?
CONvid19

2
我不确定这是否适用于我是否需要一个变量属于其中的一组。下面的其他答案对此更为直观,并且不要将正则表达式分解为几个表达式。
吉瓦尔

48
if re.search(r"\b(?<=\w)%s\b(?!\w)" % TEXTO, subject, re.IGNORECASE):

这会将TEXTO中的内容作为字符串插入到正则表达式中。



6

我发现通过将多个较小的模式串在一起来构建正则表达式模式非常方便。

import re

string = "begin:id1:tag:middl:id2:tag:id3:end"
re_str1 = r'(?<=(\S{5})):'
re_str2 = r'(id\d+):(?=tag:)'
re_pattern = re.compile(re_str1 + re_str2)
match = re_pattern.findall(string)
print(match)

输出:

[('begin', 'id1'), ('middl', 'id2')]

4

我同意以上所有条件,除非:

sys.argv[1] 就像 Chicken\d{2}-\d{2}An\s*important\s*anchor

sys.argv[1] = "Chicken\d{2}-\d{2}An\s*important\s*anchor"

您不想使用re.escape,因为在这种情况下,您希望它的行为类似于正则表达式

TEXTO = sys.argv[1]

if re.search(r"\b(?<=\w)" + TEXTO + "\b(?!\w)", subject, re.IGNORECASE):
    # Successful match
else:
    # Match attempt failed

2

我需要搜索彼此相似的用户名,Ned Batchelder所说的话非常有用。但是,当我使用re.compile创建我的搜索项时,发现输出更清晰:

pattern = re.compile(r"("+username+".*):(.*?):(.*?):(.*?):(.*)"
matches = re.findall(pattern, lines)

可以使用以下命令打印输出:

print(matches[1]) # prints one whole matching line (in this case, the first line)
print(matches[1][3]) # prints the fourth character group (established with the parentheses in the regex statement) of the first line.

1

您可以使用formatgrammer suger 尝试另一种用法:

re_genre = r'{}'.format(your_variable)
regex_pattern = re.compile(re_genre)  

0

您也可以为此使用format关键字。Format方法将{}占位符替换为您作为参数传递给format方法的变量。

if re.search(r"\b(?=\w)**{}**\b(?!\w)".**format(TEXTO)**, subject, re.IGNORECASE):
    # Successful match**strong text**
else:
    # Match attempt failed

0

更多例子

我有带有流文件的configus.yml

"pattern":
  - _(\d{14})_
"datetime_string":
  - "%m%d%Y%H%M%f"

在我使用的python代码中

data_time_real_file=re.findall(r""+flows[flow]["pattern"][0]+"", latest_file)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.