Regex: найти подстроки с шаблоном с некоторыми условиями

Я пытаюсь подготовить шаблон, чтобы найти все подстроки из текста с этим форматом

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))]+'

Не могли бы вы помочь мне изменить это и объяснить, что я делаю неправильно?

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
0
54
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Если ваши совпадения находятся внутри границ пробела, вы можете использовать

(?<!\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!=''] )

См. эта демонстрация Python.

Выход:

['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 предназначены для фильтрации нежелательных совпадений.

Спасибо за объяснение! Я пытаюсь найти это в тексте, поэтому я удалил ^ и $, но после этого у меня все еще есть substr вроде ailto:user

ldevyataykina 18.03.2022 13:49

@ldevyataykina Второе решение кажется мне наиболее полным.

Wiktor Stribiżew 18.03.2022 14:12
Ответ принят как подходящий

Ты можешь попробовать:

(?<!\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. И еще один важный момент - я пытаюсь извлечь все эти подстроки из огромного куска текста.

ldevyataykina 18.03.2022 13:46

@JvdV Я сомневаюсь, что границы пробелов будут работать из-за system:microsoft, (см. запятую в конце), но я также добавил это решение в свой ответ. Единственное решение, которое я вижу, - это то, которое основано на лучшем трюке с регулярными выражениями, поскольку 1) мы не можем полагаться на границы слов, поскольку совпадение содержит символы, не являющиеся словами, 2) кажется, что за совпадениями следуют символы, отличные от символов пробелов. Кроме того, использование .*? в прогнозе в этой ситуации является хрупким, поскольку оно может привести к превышению соответствия.

Wiktor Stribiżew 18.03.2022 14:14

Я думаю, что вы правы насчет этих моментов. Ранее я изменился на \S*, но я думаю, что второй шаблон в вашем ответе лучше всего подходит, если учесть все проблемы с пунктуацией, с которыми OP может столкнуться при поиске в большом тексте. @ВикторСтрибижев

JvdV 18.03.2022 14:35

Другие вопросы по теме