【问题标题】:How to match line beginning and end in a multi-line string如何匹配多行字符串中的行开头和结尾
【发布时间】:2019-04-24 22:09:00
【问题描述】:

我想匹配多行字符串中的整行(此代码是检查正确输出格式的单元测试的一部分)。

Python 3.5.2 (default, Nov 12 2018, 13:43:14) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import re
>>> re.match(r".*score = 0\.59.*", r"score = 0.65\nscore = 0.59\nscore = 1.0", re.MULTILINE)
<_sre.SRE_Match object; span=(0, 39), match='score = 0.65\\nscore = 0.59\\nscore = 1.0'>

这很好用,我可以匹配多行字符串中的任何内容。但是,我想确保我匹配整行。文档说^$ 在使用re.MULTILINE 时应该匹配行的开头和结尾。但是,这对我不起作用:

>>> re.match(r".*^score = 0\.59$.*", r"score = 0.65\nscore = 0.59\nscore = 1.0", re.MULTILINE)
>>> 

下面是我做的一些实验:

>>> import os
>>> re.match(r".*^score = 0\.59$.*", "score = 0.65{}score = 0.59{}score = 1.0".format(os.linesep, os.linesep), re.MULTILINE)
>>>
>>> re.match(r".*^score = 0\.65$.*", "score = 0.65{}score = 0.59{}score = 1.0".format(os.linesep, os.linesep), re.MULTILINE)
<_sre.SRE_Match object; span=(0, 12), match='score = 0.65'>
>>> re.match(r".*^score = 0\.65$.*", r"score = 0.65\nscore = 0.59\nscore = 1.0", re.MULTILINE)
>>> 

我想我错过了一些相当简单的东西,但无法弄清楚。

【问题讨论】:

  • 试试flags=re.DOTALL
  • 变色你
  • 据我了解,您想匹配第二行。问题是 .* 只匹配一行,不包括换行符。您很可能希望 re.DOTALLlazy 量词 (.*?) 结合使用。
  • 删除原始字符串:re.match(r".*^score = 0\.65$.*", "score = 0.65\nscore = 0.59\nscore = 1.0", re.MULTILINE)

标签: python regex python-3.x


【解决方案1】:

问题是,由于您使用原始字符串作为字符串,\n 被视为......好吧\ 然后n。正则表达式将理解 \n 在模式中,但在输入字符串中不理解。

此外,即使在那里不重要,也请始终使用 flags= 关键字,因为某些正则表达式函数有一个额外的 count 参数,这可能会导致错误。

像这样:

re.match(r".*^score = 0\.65$.*", "score = 0.65\nscore = 0.59\nscore = 1.0", flags=re.MULTILINE)
<_sre.SRE_Match object; span=(0, 12), match='score = 0.65'>

正如我在 cmets 中指出的,.* 需要 re.DOTALL 来匹配换行符

>>> re.match(r".*^score = \d+\.\d+$.*", "score = 0.65\nscore = 0.59\nscore = 1.0", re.MULTILINE|re.DOTALL)
<_sre.SRE_Match object; span=(0, 37), match='score = 0.65\nscore = 0.59\nscore = 1.0'>

(如 Python regex, matching pattern over multiple lines.. why isn't this working?How do I match any character across multiple lines in a regular expression? 中所述,如果不是原始字符串位,这可能是重复的)

(对不起,我的浮点正则表达式可能有点弱,你可以找到更好的)

【讨论】:

  • 是的,这似乎可行。我搞砸了原始字符串与非原始字符串,并没有注意到 DOTALL 选项。谢谢你,也谢谢你的额外建议!
  • @WiktorStribiżew 是的,有 2 个问题。原始字符串和 DOTALL 的东西。谢谢。我回答只是因为原始字符串的东西,它没有被重复
  • 我通常不会那样做,但在这里我真的不明白,投反对票这么好。
【解决方案2】:

你需要匹配一个非原始字符串并且使用DOTALL模式:

print re.match(r".*^score = 0\.59$.*", "score = 0.65\nscore = 0.59\nscore = 1.0",
    re.MULTILINE|re.DOTALL)

<_sre.SRE_Match object at 0x7fd2426d0648>

【讨论】:

  • 是的,这似乎可行。我搞砸了原始字符串与非原始字符串,并没有注意到 DOTALL 选项。谢谢!抱歉,我无法检查两个答案为“解决了我的问题”
  • @k6ps Wiktor 欺骗了你的问题,但他基本上对每个正则表达式问题都这样做,所以不要为此感到难过。
  • 在某些时候,当你非常喜欢一个主题时,一切都是骗人的。但是在那一个上,原始字符串位没有被覆盖。
  • @Jean-FrançoisFabre 确实需要有人在 Meta 网站上就此展开广泛讨论。我会告诉你,SQL 标记上的重复阈值肯定似乎比正则表达式低很多。关于哪个级别的工程师,这个问题是重复的?
  • 我想我要重新打开它,引用 Wiktor 作为骗子留下的链接,因为重复只回答部分问题(我的第一条评论已经回答了这个问题,然后我发现了原始字符串位)@TimBiegeleisen : 重新打开 :)
【解决方案3】:

你问题的真正答案是你只混淆了matchsearch

>>> import os, re
>>> print(re.match(r".*^score = 0\.59$.*", "score = 0.65\nscore = 0.59\nscore = 1.0", flags=re.MULTILINE))
None
>>> print(re.search(r".*^score = 0\.59$.*", "score = 0.65\nscore = 0.59\nscore = 1.0", flags=re.MULTILINE))
<_sre.SRE_Match object; span=(13, 25), match='score = 0.59'>
>>> 

这就是为什么您的一个非原始示例有效,而另一个无效的原因。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-28
    • 1970-01-01
    • 1970-01-01
    • 2021-11-06
    • 2011-11-19
    相关资源
    最近更新 更多