如何保存正则表达式用户输入值(Python)

时间:2012-02-07 10:00:49

标签: python regex

我正在用Python制作一个简单的聊天机器人。它有一个带有正则表达式的文本文件,有助于生成输出。用户输入和bot输出由|字符分隔。

my name is (?P<'name'>\w*) | Hi {'name'}!

这适用于单组输入和输出响应,但我希望机器人能够存储用户输入的正则表达式值,然后再次使用它们(即给机器人一个'记忆')。例如,我想让bot存储'name'的值输入,以便我可以在规则中使用它:

my name is (?P<'word'>\w*) | You said your name is {'name'} already!
my name is (?P<'name'>\w*) | Hi {'name'}!

对于'name'没有任何价值,机器人将首先输出'Hi steve',一旦机器人确实有这个值,'word'规则将适用。鉴于我构建程序的方式,我不确定这是否可行。我做了这个,以便将文本文件制作成字典,其中键和值由|分隔当用户输入一些文本时,程序会比较用户输入是否与字典中存储的输入相匹配,并打印出相应的机器人响应(如果没有找到匹配,也会有“其他”情况)。

我必须在过程的比较部分发生一些事情,以便保存用户的正则表达式文本,然后以某种方式替换回字典。我的所有正则表达式都有不同的名称与它们相关联(没有两个'word'实例,例如......有'word','word2'等),我这样做是因为我认为它会使这个部分过程更容易。尽管如此,我可能已经完全错误地构建了这个任务。

编辑:代码

import re

io = {}

with open("rules.txt") as brain:
     for line in brain:
        key, value = line.split('|')
        io[key] = value

string = str(raw_input('> ')).lower()+' word'

x = 1

while x == 1:
    for regex, output in io.items():
        match = re.match(regex, string)
        if match:
            print(output.format(**match.groupdict()))
            string = str(raw_input('> ')).lower()+' word'
    else:
        print ' Sorry?'
        string = str(raw_input('> ')).lower()+' word'

2 个答案:

答案 0 :(得分:0)

好的,让我看看我是否明白这一点:

  • 您想要一个键值对字典。这将是聊天机器人的“记忆”。
  • 您希望将正则表达式规则应用于用户输入。但是可能适用的规则取决于存储器字典中已存在哪些键:如果尚未定义“name”,则应用定义“name”的规则;但如果是,那么提到“单词”的规则就适用了。

在我看来,您需要附加规则的更多信息。例如,您在上面给出的“单词”规则实际上不应该在字典中添加“单词”,否则它只会应用一次(想象一下,如果用户一直试图说“我的名字是x”超过两次)。< / p>

这会让您对如何继续进行更多了解吗?

哦,顺便说一下,我认为“|”对于分隔符来说是一个糟糕的选择,因为它可以出现在正则表达式中。不知道该建议:“||”怎么样?

答案 1 :(得分:0)

我很难理解算法的原理,因为我不习惯使用命名组 以下代码是我解决问题的方法,我希望它会给你一些想法。

我认为只有一本字典不是一个好的原则,它增加了推理和算法的复杂性。所以我将代码基于两个词典:direg和memory

这两个词典的键是组的索引,而不是所有索引,只有一些特定的索引,组的索引是每个单独模式中的最后一个。
因为,为了好玩,我决定正则表达式必须能够有几个组。

我在代码中称为单个模式的是以下字符串:

"[mM]y name [Ii][sS] (\w*)"

"[Ii]n repertory (\w*) I [wW][aA][nN][tT] file (\w*)"

"[Ii] [wW][aA][nN][tT] to ([ \w]*)"

您看到第二个单独的模式有2个捕获组:因此有3个单独的模式,但在所有各个组中总共有4个组。

因此,字典的创建需要额外注意,以考虑最后一个匹配组的索引(我使用正则表达式MatchObject的名称​​ lastindex 的属性帮助) )可能与正则表达式中存在的单个正则表达式的编号不对应:解释比理解更难。这就是为什么我在函数 distr()中计算字符串 {0} {1} {2} {3} {4}等的出现,其数量必须是与相应的单个模式中定义的组数相同。

我发现Laurence D'Oliveiro建议使用'||'而不是'|'作为分隔符有趣。

我的代码模拟了一个会话,其中完成了几个输入:

import re

regi = ("[mM]y name [Ii][sS] (\w*)"
        "||Hi {0}!"
        "||You said that your name was {0} !!!",

        "[Ii]n repertory (\w*) I [wW][aA][nN][tT] file (\w*)"
        "||OK here's your file {0}\\{1} :"
        "||I already gave you the file {0}\\{1} !",

        "[Ii] [wW][aA][nN][tT] to ([ \w]*)"
        "||OK, I will do {0}"
        "||You already did {0}. Do yo really want again ?")


direg  = {}
memory = {}
def distr(regi,cnt = 0,di = direg,mem = memory,
          regnb = re.compile('{\d+}')):
    for i,el in enumerate(regi,start=1):
        sp = el.split('||')
        cnt += len(regnb.findall(sp[1]))
        di[cnt] = sp[1]
        mem[cnt] = sp[2]
        yield sp[0]

regx = re.compile('|'.join(distr(regi)))
print 'direg :\n',direg
print
print 'memory :\n',memory
for inp in ('I say that my name is Armano the 1st',
            'In repertory ONE I want file SPACE',
            'I want to record music',
            'In repertory ONE I want file SPACE',
            'I say that my name is Armstrong',
            'But my name IS Armstrong now !!!',
            'In repertory TWO I want file EARTH',
            'Now my name is Helena'):

    print '\ninput  ==',inp

    mat = regx.search(inp)
    if direg[mat.lastindex]:
        print 'output ==',direg[mat.lastindex]\
              .format(*(d for d in mat.groups() if d))
        direg[mat.lastindex] = None
        memory[mat.lastindex] = memory[mat.lastindex]\
                                .format(*(d for d in mat.groups() if d))
    else:
        print 'output ==',memory[mat.lastindex]\
              .format(*(d for d in mat.groups() if d))
        if not memory[mat.lastindex].startswith('Sorry'):
            memory[mat.lastindex] = 'Sorry, ' \
                                    + memory[mat.lastindex][0].lower()\
                                    + memory[mat.lastindex][1:]

结果

direg :
{1: 'Hi {0}!', 3: "OK here's your file {0}\\{1} :", 4: 'OK, I will do {0}'}

memory :
{1: 'You said that your name was {0} !!!', 3: 'I already gave you the file {0}\\{1} !', 4: 'You already did {0}. Do yo really want again ?'}

input  == I say that my name is Armano the 1st
output == Hi Armano!

input  == In repertory ONE I want file SPACE
output == OK here's your file ONE\SPACE :

input  == I want to record music
output == OK, I will do record music

input  == In repertory ONE I want file SPACE
output == I already gave you the file ONE\SPACE !

input  == I say that my name is Armstrong
output == You said that your name was Armano !!!

input  == But my name IS Armstrong now !!!
output == Sorry, you said that your name was Armano !!!

input  == In repertory TWO I want file EARTH
output == Sorry, i already gave you the file ONE\SPACE !

input  == Now my name is Helena
output == Sorry, you said that your name was Armano !!!