ChatGPT解决这个技术问题 Extra ChatGPT

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

我想在 regex 中使用 variable,如何在 Python 中执行此操作?

TEXTO = sys.argv[1]

if re.search(r"\b(?=\w)TEXTO\b(?!\w)", subject, re.IGNORECASE):
    # Successful match
else:
    # Match attempt failed
您使用字符串连接

N
Ned Batchelder

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

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 的使用,以便如果您的文本包含特殊字符,它们将不会被解释为特殊字符。


如果你的变量先出现怎么办? r'' + foo + 'bar' ?
@deed02392 如果您执行 re.escape(foo),则不需要 r'',无论如何您都应该这样做。实际上,我认为 re 将给出的任何内容解释为 unicode 字符串,无论您是否为 r 加上前缀。
.format() 是否可以代替 re.escape 或者 re.escape() 是否必要?
@praxiteles 你找到答案了吗?
我不确定这是否适用于我需要有一组变量是其中的一部分。下面的其他答案看起来更直观,并且不要将正则表达式分解为几个表达式。
K
KiriSakow

从 python 3.6 开始,您还可以使用 Literal String Interpolation,“f-strings”。在您的特定情况下,解决方案是:

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

编辑:

由于评论中有一些关于如何处理特殊字符的问题,我想扩展我的答案:

原始字符串('r'):

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

简而言之:

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

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")

注意:对于任何版本 >= python 3.7:!"%',/:;<=>@` 不会被转义。只有在正则表达式中有意义的特殊字符仍然被转义。自 Python 3.3 起,_ 未转义。(s. here

大括号:

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

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

截至 2020 年,这是在正则表达式中使用变量的最简单、最 Python 的方式
这绝对是一个WOW。
有人可以在这里解释“rf”的意义吗
@HarshaReddy:'r':这个字符串是一个原始字符串:如果你不使用它,'\b' 将被转换为退格字符(docs.python.org/3/howto/regex.html#more-pattern-power)。 'f' 告诉 python 这是一个'f-string',s。上面的链接,并使您可以将变量写入花括号-
如何在 f 字符串中编写量词:fr"foo{{1,5}}"(双括号)
W
Wiktor Stribiżew
if re.search(r"\b(?<=\w)%s\b(?!\w)" % TEXTO, subject, re.IGNORECASE):

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


W
Wiktor Stribiżew
rx = r'\b(?<=\w){0}\b(?!\w)'.format(TEXTO)

如果我在我的正则表达式中使用 {4} 来表达我想要之前出现的任何内容,这不会成为问题吗?
D
Deepak Nagarajan

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

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')]

P
Pedro Lobito

我同意以上所有内容,除非:

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

K
Kevin Chou

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

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

j
jdelaporte

我需要搜索彼此相似的用户名,而 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.

A
Ardhi

这是您可以使用的另一种格式(在 python 3.7 上测试)

regex_str = r'\b(?<=\w)%s\b(?!\w)'%TEXTO

我发现当你不能使用 {} 作为变量时它很有用(这里用 %s 代替)


H
Haneef Mohammed

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

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

P
Pedro Lobito

更多示例

我有带有流文件的 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)