匹配多行文本块的正则表达式

新手上路,请多包涵

在匹配跨越多行的文本时,我在让 Python 正则表达式工作时遇到了一些麻烦。示例文本是(’\n’ 是换行符)

 some Varying TEXT\n
\n
DSJFKDAFJKDAFJDSAKFJADSFLKDLAFKDSAF\n
[more of the above, ending with a newline]\n
[yep, there is a variable number of lines here]\n
\n
(repeat the above a few hundred times).

我想捕获两件事:“some_Varying_TEXT”部分,以及在一次捕获中位于它下方两行的所有大写文本行(我可以稍后删除换行符)。我尝试了几种方法:

 re.compile(r"^>(\w+)$$([.$]+)^$", re.MULTILINE) # try to capture both parts
re.compile(r"(^[^>][\w\s]+)$", re.MULTILINE|re.DOTALL) # just textlines

以及其中的许多变体,但没有运气。最后一个似乎与文字行一一对应,这不是我真正想要的。我可以抓住第一部分,没问题,但我似乎无法抓住 4-5 行大写文本。我希望 match.group(1) 是 some_Varying_Text 和 group(2) 是 line1+line2+line3+etc 直到遇到空行。

如果有人好奇的话,它应该是构成蛋白质的一系列氨基酸。

原文由 Jan 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 809
2 个回答

试试这个:

 re.compile(r"^(.+)\n((?:\n.+)+)", re.MULTILINE)

我认为您最大的问题是您期望 ^$ 锚点匹配换行符,但它们没有。在多行模式下, ^ 匹配换行符 的位置, $ 匹配换行符 的位置。

另请注意,换行符可以包含换行符 ( \n )、回车符 ( \r ) 或回车符+换行符 ( \r\n )。如果您不确定您的目标文本是否只使用换行符,您应该使用这个更具包容性的正则表达式版本:

 re.compile(r"^(.+)(?:\n|\r\n?)((?:(?:\n|\r\n?).+)+)", re.MULTILINE)

顺便说一句,您不想在这里使用 DOTALL 修饰符;您依赖于点匹配 换行符以外的所有内容的事实。

原文由 Alan Moore 发布,翻译遵循 CC BY-SA 4.0 许可协议

这将起作用:

 >>> import re
>>> rx_sequence=re.compile(r"^(.+?)\n\n((?:[A-Z]+\n)+)",re.MULTILINE)
>>> rx_blanks=re.compile(r"\W+") # to remove blanks and newlines
>>> text="""Some varying text1
...
... AAABBBBBBCCCCCCDDDDDDD
... EEEEEEEFFFFFFFFGGGGGGG
... HHHHHHIIIIIJJJJJJJKKKK
...
... Some varying text 2
...
... LLLLLMMMMMMNNNNNNNOOOO
... PPPPPPPQQQQQQRRRRRRSSS
... TTTTTUUUUUVVVVVVWWWWWW
... """
>>> for match in rx_sequence.finditer(text):
...   title, sequence = match.groups()
...   title = title.strip()
...   sequence = rx_blanks.sub("",sequence)
...   print "Title:",title
...   print "Sequence:",sequence
...   print
...
Title: Some varying text1
Sequence: AAABBBBBBCCCCCCDDDDDDDEEEEEEEFFFFFFFFGGGGGGGHHHHHHIIIIIJJJJJJJKKKK

Title: Some varying text 2
Sequence: LLLLLMMMMMMNNNNNNNOOOOPPPPPPPQQQQQQRRRRRRSSSTTTTTUUUUUVVVVVVWWWWWW


关于此正则表达式的一些解释可能会有用: ^(.+?)\n\n((?:[A-Z]+\n)+)

  • 第一个字符 ( ^ ) 表示“从一行的开头开始”。请注意,它与换行符本身不匹配(与 $ 相同:它的意思是“就在换行符之前”,但它与换行符本身不匹配)。
  • 然后 (.+?)\n\n 表示“匹配尽可能少的字符(允许所有字符)直到到达两个换行符”。结果(没有换行符)放在第一组中。
  • [A-Z]+\n 表示“匹配尽可能多的大写字母,直到到达换行符。这定义了我所说的 _文本行_。
  • ((?: textline )+) 表示匹配一个或多个 文本 行,但不要将每一行放在一个组中。相反,将 所有 文本行 放在一组中。
  • 如果你想在末尾强制使用双换行符,你可以在正则表达式中添加一个 final \n
  • 此外,如果您不确定您将获得哪种类型的换行符( \n\r\r\n )然后通过替换每个出现的正则表达式 \n (?:\n|\r\n?)

原文由 MiniQuark 发布,翻译遵循 CC BY-SA 2.5 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题