Python re.match соответствует только перед первым \ n - PullRequest
3 голосов
/ 07 октября 2019

Я пытаюсь обернуть ping с помощью Python (3.7.4), используя subprocess и re.

. stdout из функции subprocess является байтовым массивом, поэтому мне пришлось изменитьтип регулярного выражения в соответствии с регистром.

    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 с использованием str() или .decode() не оказали никакого влияния на вывод.

Проверено несколькими различными онлайн-инструментами, все они работали, есть идеи?

1 Ответ

1 голос
/ 07 октября 2019

Когда вы используете 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 предшествует несколько символов.

Toобъяснить 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...