如何在Python中使用正则表达式与占位符文本?

5 投票
4 回答
7282 浏览
提问于 2025-04-17 12:19

我正在做一个Python项目,需要用户输入文本。如果输入的文本符合程序支持的格式,程序就会输出一个包含用户关键词的回复(这其实是一个简单的聊天机器人)。这些格式被存储在一个文本文件中,里面有用户输入的格式和对应的回答格式。

比如,这个文本文件的内容是这样的,左边是用户输入,右边是输出:

my name is <-name> | Hi there, <-name>

所以如果用户写了my name is johnny,我希望程序能知道johnny<-name>这个变量,然后打印出回复Hi there, johnny

如果能给我一些指引就太好了!我之前从来没有用过正则表达式,虽然我看过一篇关于如何使用它们的文章,但遗憾的是那篇文章主要讲的是如何匹配特定的单词,对我帮助不大。

4 个回答

1

问关于正则表达式(REGEXP)的问题,往往会得到一些基础操作的回答,比如如何拆分句子,或者如何在句子中查找像'my' + 'name' + 'is'这样的词组合等等。

其实,你可以通过阅读现有的文档和开源程序来学到这些。正则表达式并不简单。不过,如果你想要真正理解发生了什么,以便能够修改和扩展你的程序,你还是需要自己多了解一些,不要只是照搬这里的答案。

但你可能还想要更全面的内容。因为你提到要构建一个“聊天机器人”,你可能想看看其他人是如何处理这个任务的——这远远超出了正则表达式的范畴。比如:

如果用户输入'my name is johnny',我希望程序能知道'johnny'是'<-name>'这个变量……

从你的问题来看,不太清楚这个程序应该有多复杂。如果他输入了

'Johnny is my name.'

或者

'Hey, my name is John X., but call me johnny.'

呢?

6

你需要做一个分组匹配,然后提取出搜索的组。

首先,你需要 import re - re 是 Python 中处理正则表达式的模块。假设用户输入的内容保存在一个变量中,叫做 user_input。

接下来,你要使用 re.sub 方法来匹配你的字符串,并用其他内容替换它。

output = re.sub(input_regex, output_regex, user_input)

关于正则表达式,首先你可以写出你想要的具体内容:

input_regex = 'my name is '

如果你想要它从行的开头开始匹配,你需要在前面加一个插入符号(^):

input_regex = '^my name is '

然后你需要一个组来匹配任意字符串 .+(. 表示任何字符,+ 表示前面的字符出现一次或多次),直到行的结尾($)。

input_regex = '^my name is .+$'

现在你需要把这个放入一个命名组中。命名组的格式是 "(?P)" - 注意那些尖括号是字面意思。

input_regex = '^my name is (?P<name>.+)$'

现在你有了一个正则表达式,它会匹配并给出一个名为 "name" 的匹配组,里面包含用户的名字。输出字符串需要用 "\g" 来引用这个匹配组。

output_regex = 'Hi there, \g<name>'

把这些组合在一起,你可以用一行代码来实现(还有导入的部分):

import re
output = re.sub('^my name is (?P<name>.+)$', 'Hi there, \g<name>', user_input)
9

这里有一个例子:

import re

io = [
    ('my name is (?P<name>\w+)', 'Hi there, {name}'),
]

string = input('> ')
for regex, output in io:
    match = re.match(regex, string)
    if match:
        print(output.format(**match.groupdict()))
        break

我来给你讲解一下:


'my name is (?P<name>\w+)'

(?P<name>...) 会把后面的部分(\w+)存储在一个叫 name 的名字下,这个名字会在我们后面使用到。


match = re.match(regex, string)

这个是用来在给定的输入中查找 regex。注意,re.match 只会在输入的 开头 匹配,如果你不想有这个限制,可以用 re.search


如果匹配成功:

output.format(**match.groupdict())

match.groupdict 会返回一个字典,这个字典的键是由 (?P<name>...) 定义的,值是它们对应的匹配结果。** 会把这些键值对传递给 .format,在这个例子中,Python 会把它转换成 output.format(name='matchedname')


要从文件中构建 io 字典,可以这样做:

io = []
with open('input.txt') as file_:
    for line in file:
        key, value = line.rsplit(' | ', 1)
        io.append(tuple(key, value))

撰写回答