Я пытаюсь подготовить шаблон, чтобы найти все подстроки из текста с этим форматом
system:microsoft,
flow:to_server,
vho:file-was-closed,
heur250:unknown.file
Кроме того, я хочу исключить подстроки, в которых части до или после :
содержат только цифры.
03:00
file:123
Я не хочу перехватывать подстроки, в которых часть перед :
равна mailto
mailto:user
И я не хочу ловить подстроки, где части до или после :
заканчиваются некоторыми расширениями, такими как jpg
, png
cid:image003.png
Я написал шаблон, но он не работает должным образом.
pattern = r'(?!^\d+$)(?!mailto)[\w\d\.-]+:[\w\d\.-(?!(jpg|png))]+'
Не могли бы вы помочь мне изменить это и объяснить, что я делаю неправильно?
Если ваши совпадения находятся внутри границ пробела, вы можете использовать
(?<!\S)(?!mailto:|\d+:)[\w.-]+(?<!\.jpg|\.png):(?!\d+(?!\S))[\w.-]+(?!\S)(?<!\.jpg|\.png)
См. демонстрация регулярных выражений.
Подробности:
(?<!\S)
- левая граница пробела(?!mailto:|\d+:)
- сразу справа, не может быть mailto:
или одной или нескольких цифр, за которыми следует символ :
[\w.-]+
- одно или несколько слов, .
или -
символов(?<!\.jpg|\.png)
- нельзя .jpg
или .png
сразу слева:
- двоеточие(?!\d+(?!\S))
- разрешены только цифры до пробела или конца строки[\w.-]+
- одно или несколько слов, .
или -
символов(?!\S)
- правая граница пробела(?<!\.jpg|\.png)
- .jpg
или .png
сразу слева не допускаются.Если ваши совпадения расположены в любом контексте вы можете использовать такое решение, как
import re
text = "system:microsoft flow:to_server vho:file-was-closed heur250:unknown.file, file.png:word, 03:00, file:123, mailto:user, cid:image003.png"
pattern = r'\bmailto:[\w.-]+|\b\d+:[\w.-]+|[\w.-]+:\d+|[\w.-]+:[\w.-]*\.(?:jpg|png)(?![\w.-])|[\w.-]*\.(?:jpg|png):[\w.-]+|([\w.-]+:[\w.-]+)'
print( [x for x in re.findall(pattern, text) if x!=''] )
Выход:
['system:microsoft', 'flow:to_server', 'vho:file-was-closed', 'heur250:unknown.file']
Обратите внимание, что это решение основано на "лучший трюк с регулярными выражениями". Подробности:
\bmailto:[\w.-]+|
- целое слово mailto:
, а затем одно или несколько слов, .
или -
символы, или\b\d+:[\w.-]+|
- граница слова, одна или несколько цифр, :
, а затем одно или несколько слов, .
или -
символы, или[\w.-]+:\d+|
- одно или несколько слов, .
или -
символы, :
, одна или несколько цифр[\w.-]+:[\w.-]*\.(?:jpg|png)(?![\w.-])|
- одно или несколько слов, .
или -
символы, :
, ноль или более слов, .
или -
символы, затем .
и jpg
или png
без слова, .
или -
символы, или[\w.-]*\.(?:jpg|png):[\w.-]+|
- ноль или более слов, .
или -
символы, .
, jpg
или png
, :
, а затем одно или несколько слов, .
или -
символы, или([\w.-]+:[\w.-]+)
- Группа 1 (выведем только это значение): одно или несколько слов, символы .
или -
, :
и одно или несколько слов, символы .
и -
.Все части перед последним шаблоном группы 1 предназначены для фильтрации нежелательных совпадений.
@ldevyataykina Второе решение кажется мне наиболее полным.
Ты можешь попробовать:
(?<!\S)(?!mailto|(?:\S*:)?(?:\d+|\S*\.(?:jp|pn)g)([\s:]|$))[\w.-]+:[\w.-]+(?!\S)
См. онлайн демо. По общему признанию, последняя часть шаблона может быть более конкретной, чтобы такие вещи, как ...:...
, не были действительными, но это зависит от вас, я думаю.
(?<!\S)
- Утверждать позицию не предшествует непробельный символ;(?!mailto|(?:\S*:)?(?:\d+|\S*\.(?:jp|pn)g)([\s:]|$))
- Отрицательный просмотр вперед с чередованием: избегайте «mailto:», избегайте завершающих «.jpg» или «.png» или просто цифр по обе стороны от двоеточия;[\w.-]+:[\w.-]+
— шаблон, соответствующий как минимум 1+ символам данного класса по обе стороны от двоеточия;(?!\S)
- За позициями Assert не следует непробельный символ.Благодарю вас! Но findall
все равно возвращает мне что-то вроде 'ailto:kolesnikov.vn'
, gmt-05:00
. И еще один важный момент - я пытаюсь извлечь все эти подстроки из огромного куска текста.
@JvdV Я сомневаюсь, что границы пробелов будут работать из-за system:microsoft,
(см. запятую в конце), но я также добавил это решение в свой ответ. Единственное решение, которое я вижу, - это то, которое основано на лучшем трюке с регулярными выражениями, поскольку 1) мы не можем полагаться на границы слов, поскольку совпадение содержит символы, не являющиеся словами, 2) кажется, что за совпадениями следуют символы, отличные от символов пробелов. Кроме того, использование .*?
в прогнозе в этой ситуации является хрупким, поскольку оно может привести к превышению соответствия.
Я думаю, что вы правы насчет этих моментов. Ранее я изменился на \S*
, но я думаю, что второй шаблон в вашем ответе лучше всего подходит, если учесть все проблемы с пунктуацией, с которыми OP может столкнуться при поиске в большом тексте. @ВикторСтрибижев
Спасибо за объяснение! Я пытаюсь найти это в тексте, поэтому я удалил
^
и$
, но после этого у меня все еще есть substr вродеailto:user