使用Python Madlibs自动完成无聊的工作:替换匹配的正则表达式(丢失标点符号)时会遇到麻烦

时间:2018-07-28 21:45:30

标签: python regex

这是我的代码:

import os, re

def madLibs():
    madLibsDirectory = 'madLibsFiles'
    os.chdir(madLibsDirectory)
    madLibsFile = 'panda.txt'
    madLibsFile = open(madLibsFile)
    file = madLibsFile.read()
    madLibsFile.close()

    wordRegex = re.compile(r"ADJECTIVE|VERB|ADVERB|NOUN")
    file = file.split() # split the madlib into a list with each word.
    for word in file:
    # check if word matches regex
        if wordRegex.match(word):
            foundWord = wordRegex.search(word) # create regex object on word
            newWord = input(f'Please Enter A {foundWord.group()}: ') # recieve word
            file[file.index(word)] = wordRegex.sub(newWord, foundWord.group(), 1)  
    file = ' '.join(file)
    print(file)

def main():
    madLibs()

if __name__ == '__main__':
    main()

问题行为file[file.index(word)] = wordRegex.sub(newWord, foundWord.group(), 1)

当我的程序在单词ADJECTIVE,VERB,ADVERB和NOUN上运行时,它将提示用户输入单词并将该占位符替换为输入。当前,此代码正确替换了HOWEVER一词,它不保留标点符号。 例如,这里是panda.txt:

  

这只熊猫走到名词,然后是动词。附近的名词   不受这些事件的影响。

当我用“吃”代替VERB时,它会这样做,但删除句号:“ ...然后在附近吃A”。

我确定这个答案不会太复杂,但是不幸的是我的REGEX知识还不是很出色。 谢谢!

1 个答案:

答案 0 :(得分:0)

您已正确识别出有问题的行:

file[file.index(word)] = wordRegex.sub(newWord, foundWord.group(), 1)

此行的问题在于,您仅替换foundWord.group()的一部分,该部分仅包含匹配的单词,而没有出现在其周围的标点符号。

一个简单的解决方法是完全放下foundWord,仅使用word作为替换文字。上面的行将变为:

file[file.index(word)] = wordRegex.sub(newWord, word, 1)

应该可以!但是,您可以通过许多其他方式来改进代码。例如,您无需在file上搜索word来获取分配的正确索引,而是应使用enumerate来获取每个word的索引:

for i, word in enumerate(file):
    if ...
       ...
       file[i] = ...

或者您可以进行更大的更改。 re.sub函数(以及编译模式对象的等效方法)可以在一次通过中进行多次替换,并且可以使用一个函数而不是字符串来进行替换。每次文本中的模式匹配时,将使用匹配对象调用该函数。那么,为什么不使用功能提示用户输入替换词,并一次性替换所有关键字呢?

def madLibs():
    madLibsDirectory = 'madLibsFiles'
    os.chdir(madLibsDirectory)
    filename = 'panda.txt'           # changed this variable name, to avoid duplication
    with open(filename) as file:     # a with statement will automatically close the file
        text = file.read()           # renamed this variable too

    wordRegex = re.compile(r"ADJECTIVE|VERB|ADVERB|NOUN")

    modified_text = wordRegex.sub(lambda match: input(f'Please Enter A {match.group()}: '),
                                  text)     # all the substitutions happen in this one call

    print(modified_text)

lambda的调用中的wordRegex.sub等效于此命名函数:

def func(match):
    return input(f'Please Enter A {match.group()}: ')