Извлечь вхождение текста между скобками из текстового файла Python

Журнальный файл:

INFO:werkzeug:127.0.0.1 - - [20/Sep/2018 19:40:00] "GET /socket.io/?polling HTTP/1.1" 200 -
INFO:engineio: Received packet MESSAGE, ["key",{"data":{"tag1":12,"tag2":13,"tag3": 14"...}}]

Меня интересует извлечение только текста из with в скобках, который содержит ключевое слово "key", а не всех вхождений, которые соответствуют шаблону регулярного выражения ниже.

Вот что я пробовал до сих пор:

import re
with open('logfile.log', 'r') as text_file:
    matches = re.findall(r'\[([^\]]+)', text_file.read())
    with open('output.txt', 'w') as out:
        out.write('\n'.join(matches))

Это выводит все вхождения, соответствующие регулярному выражению. Желаемый вывод в output.txt будет выглядеть так:

"key",{"data":{"tag1":12,"tag2":13,"tag3": 14"...}}

person spinState010    schedule 21.09.2018    source источник
comment
Будут ли все сообщения, которые вы хотите извлечь, содержать key или это просто пример? Какую структуру можно предположить для вывода?   -  person JohanL    schedule 21.09.2018
comment
Да, нужные извлеченные сообщения будут содержать один и тот же ключ ключевого слова. Что касается структуры вывода, она должна содержать весь текст в квадратных скобках из приведенного выше примера фрагмента файла журнала.   -  person spinState010    schedule 21.09.2018
comment
Попробуйте print(re.findall(r'\[([^][]*"key"[^][]*)]', text_file.read())), если "key" может появиться где угодно внутри квадратных скобок.   -  person Wiktor Stribiżew    schedule 21.09.2018
comment
Затем вы можете сделать ту часть регулярного выражения, которую вы ищете: re.findall(r'\["key"([^\]]+)', text_file.read()). Это то, что вы ищете?   -  person JohanL    schedule 21.09.2018
comment
@JohanL Я попробовал это, и, похоже, это не сработало, хотя это было в правильном направлении. Спасибо за ответ!   -  person spinState010    schedule 21.09.2018
comment
Ах, у вас, вероятно, есть * перед вашей фразой key (что делает ее жирной, когда она написана здесь в виде текста. Если вы хотите уловить и это, это будет re.findall(r'\[\*"key"\*([^\]]+)', text_file.read()), или вы, конечно, можете использовать более общий поиск для key как в принятом ответе.   -  person JohanL    schedule 21.09.2018
comment
@JohanL Извините за путаницу, которую мог вызвать полужирный текст. Я просто хотел подчеркнуть слово «ключ». vash_the_stampede, уже взял на себя смелость отредактировать мой пост и убрать жирный шрифт.   -  person spinState010    schedule 22.09.2018


Ответы (1)


Чтобы сопоставить текст в квадратных скобках, который не может содержать [ и ] внутри, но должен содержать какой-либо другой текст, можно сопоставить класс символов с отрицанием [^][].

То есть вы можете сопоставить весь текст в квадратных скобках с \[[^][]*], и если вам нужно сопоставить какой-то текст внутри, вам нужно поместить этот текст после [^][]*, а затем добавить еще одно вхождение [^][]* перед закрывающим ].

Вы можете использовать

re.findall(r'\[([^][]*"key"[^][]*)]', text_file.read()) 

См. демонстрацию Python:

import re
s = '''INFO:werkzeug:127.0.0.1 - - [20/Sep/2018 19:40:00] "GET /socket.io/?polling HTTP/1.1" 200 - 
INFO:engineio: Received packet MESSAGE, ["key",{"data":{"tag1":12,"tag2":13,"tag3": 14"...}}]'''
print(re.findall(r'\[([^][]*"key"[^][]*)]', s)) 

Выход:

['"key",{"data":{"tag1":12,"tag2":13,"tag3": 14"...}}']
person Wiktor Stribiżew    schedule 21.09.2018
comment
Спасибо! Это сработало отлично! Просто чтобы уточнить общий способ сопоставления экземпляра, когда у нас есть key1 или key2. совпадения = re.findall(r'[([^][]*key.*[^][]*)]', text_file.read()) - person spinState010; 21.09.2018
comment
@spinState010 Это может быть key[12] или key\d+ вместо key. - person Wiktor Stribiżew; 21.09.2018