如何避免使用 Python re 库删除文本文件中正则表达式标志之间的文本块?

Posted

技术标签:

【中文标题】如何避免使用 Python re 库删除文本文件中正则表达式标志之间的文本块?【英文标题】:How do I avoid removing blocks of text between Regex flags in my text file using the the Python re library? 【发布时间】:2021-09-18 10:18:19 【问题描述】:

我目前正在尝试使用 Python re 库根据我放在这些文件中的唯一标志来剪切文本文件块。但是,如果我在我的文件中包含多个标记块的实例,我会发现所有标记块都集中在一起作为一个大块并被删除。

考虑这个示例文本文件,将其命名为test.txt

Do, a deer, a female deer
### mark
Re, a drop of golden sun
### end mark
Mi, a name I call myself
Fa, a long long way to run
### mark
So, a needle pulling thread
La, a note to follow So
Ti, a drink with jam and bread
### end mark
Now that brings us back to Do

我正在使用以下代码来剪切我想要的文本块:

def replace_file_text(path, regex, repl, flags=0):
    old_text = ""
    with open(path, "r", encoding="utf-8") as f:
        old_text = f.read()
    new_text = re.sub(regex, repl, old_text, flags=flags)
    with open(path, "w", encoding="utf-8") as f:
        f.write(new_text)

replace_file_text("test.txt", r"### mark.*### end mark", "", re.DOTALL)

我希望将文本文件转换为:

Do, a deer, a female deer
Mi, a name I call myself
Fa, a long long way to run
Now that brings us back to Do

但我最终得到的是:

Do, a deer, a female deer
Now that brings us back to Do

我知道问题出在哪里,但我不确定如何避免将我的标志实例计数为要删除的文本。

最初,我使用 sed 文本编辑器编写了一个 shell 脚本来剪切这些文本块,并且效果很好:

sed "/### mark/,/### end mark/d" test.txt > new-test.txt

有人可以向我解释为什么后一种方法有效而前一种方法无效吗?有没有人对一种相对干净的方法有任何建议,以避免在 Python 版本中删除我的标志之间的文本?

【问题讨论】:

` r"### mark.*?### end mark"` ? 是的。做到了。谢谢克里斯! 很高兴能帮上忙。此正则表达式中的 ? 使前面的 .* nongreedy。正则表达式首先向前看是否匹配### end mark。如果没有,它会前进一个位置并继续寻找和前进,直到找到那个短语。如果没有non-greedy ?.* 会读入字符串中的所有字符,然后回溯以查找该阶段的最后一次出现。 ? 也有其他用途(取决于它的位置)。它将像他的帖子中提到的damonmickelsen 那样运行。 【参考方案1】:

听起来您需要在正则表达式中添加一些特殊字符。比如特殊字符?

导致生成的 RE 匹配前面 RE 的 0 或 1 次重复。 ab?将匹配“a”或“ab”。

目前,如果没有特殊字符,它将是“贪婪的”并匹配模式的第一次和最后一次出现。查看 Python 的“re - Regular expression operation”页面的“特殊字符”部分。

我想你最终会得到这样的结果: replace_file_text("test.txt", r"(### mark).*(### end mark)?", "", re.DOTALL)

对于正则表达式,我发现反复试验是您找到正确解决方案的方法。它们既复杂又特殊。

【讨论】:

事实证明,我所需要的只是在.* 部分添加一个问号以形成r"### mark.*?### end mark"。用您使用的术语来说,这基本上使匹配尽可能不贪婪,因此我将小片段相互匹配,而不是整个匹配。不过,感谢您的帮助!

以上是关于如何避免使用 Python re 库删除文本文件中正则表达式标志之间的文本块?的主要内容,如果未能解决你的问题,请参考以下文章

re库:Python中正则表达式的处理与应用

re库:Python中正则表达式的处理与应用

如何使用Python从FTP服务器中删除文本?

Python 基础 - Day 5 Learning Note - 模块 之 标准库:RE (14) 正则表达式

如何从python中的图像中删除某些文本?

如何在 Python 3.9 中从 re.sub 中删除反斜杠