【问题标题】:Python re.match only matches before the first \nPython re.match 仅在第一个 \n 之前匹配
【发布时间】:2019-10-07 12:42:43
【问题描述】:

我正在尝试使用 subprocessre 用 Python (3.7.4) 包装 ping。

subprocess 函数中的stdout 是字节数组,因此我必须更改正则表达式类型以匹配大小写。

    import subprocess,re

    out = subprocess.run(['ping', '-c', '1', '8.8.8.8'], capture_output=True)
    print(out.stdout)
    match = re.match(br'P(..)G', out.stdout, re.DOTALL | re.MULTILINE)
    if match:
        print(match.groups())

    match = re.match(br'trans(.)', out.stdout, re.DOTALL | re.MULTILINE)
    if match:
        print(match.groups())

ping 命令的实际输出:

b'PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.\n64 bytes from 8.8.8.8: icmp_seq=1 ttl=53 time=60.7 ms\n\n--- 8.8.8.8 ping statistics ---\n1 packets transmitted, 1 received, 0% packet loss, time 0ms\nrtt min/avg/max/mdev = 60.665/60.665/60.665/0.000 ms\n'

match.groups的第一个输出:

(b'IN',)

第二个是空的(应该是(b'm',)),其实第一个\n之后的都不能匹配。

注意我有re.MULTILINE,使用str().decode() 转换为str 对输出没有任何影响。

检查了几种不同的在线工具,它们都有效,有什么想法吗?

【问题讨论】:

  • 您没有编译正则表达式来匹配。此外,多行并不像您认为的那样做......它控制 ^ 和 $ 的行为

标签: python arrays regex python-3.x


【解决方案1】:

当您使用match 匹配从第一个位置开始时,您的变量不以trans 开头,这就是它没有匹配它的原因,使用.*?trans(.) 表示trans 在中间文本,但我认为您应该使用搜索:

   match = re.search(br'trans(.)', out.stdout)

注意:

  • re.DOTALL 仅在您想在. 中包含\n 时使用,这意味着. 将匹配包括\n 在内的任何字符。
  • re.MULTILINE 默认情况下 ^ 匹配文本的开头,$ 匹配文本的结尾,但是当您使用此标志编译 REGEX 时, ^ 将匹配行首,$ 匹配行尾 (\n)。

你的问题是匹配工作检查这个例子的方式:

import re

pattern = r'HELLO (\w+)'

print(re.match(pattern, 'HELLO X').groups())  # work fine because the text start with HELLO 
m = re.match(pattern, 'CHELLO X')
print(m is None)  # didn't mach because the Text didn't start with HELLO

match 当你没有指定Hello前面有一些字符时,从第一个位置开始匹配。

解释DOTALL

import re

text = '\nHELLO X'
pattern = re.compile(r'.*?HELLO (\w+)')
pattern_dotall = re.compile(r'.*?HELLO (\w+)', re.DOTALL)

print(re.match(pattern, text) is None)  # True: . don't match \n
print(re.match(pattern_dotall, text) is None)  # False: here is included

【讨论】:

  • 那么为什么.* 不起作用而.*? 起作用?顺便说一句,我确实需要re.DOTALL,因为开头是.*?
  • 问题是匹配从第一个位置开始匹配,当你想匹配 \n 时它是真的,你应该使用标志 re.DOTALL 。你只需要re.DOTALL标志
猜你喜欢
  • 1970-01-01
  • 2023-03-11
  • 2019-11-23
  • 2021-10-01
  • 1970-01-01
  • 2014-10-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多