2016-05-15 2 views
11

Вот что я пытаюсь делать с регулярными выражениями, и я не могу понять, как это сделать. У меня большой файл и строки abc, 123 и xyz, которые появляются несколько раз по всему файлу.Регулярные выражения: Обеспечение b не происходит между a и c

Я хочу, чтобы регулярное выражение совпадало подстроку большого файла, который начинается с abc, содержит 123 где-то в середине, заканчивается xyz, и нет никаких других примеров abc или xyz в подстроках, кроме начала и конец.

Возможно ли это с регулярными выражениями?

+5

[Поскольку регулярные выражения не полностью стандартизованы, все вопросы с этим тегом должны также содержать тег, определяющий применимый язык программирования или инструмент.] (Http://stackoverflow.com/tags/regex/info) , есть ли какая-то конкретная причина, по которой вы хотите использовать регулярные выражения здесь? Это возможно, но в большинстве сред это сложнее, чем не использовать регулярные выражения. – hvd

+0

Должны быть рассмотрены разрывы строк или нет? Большой файл будет считаться строкой или одной большой строкой? –

+0

Реджейный аромат - это python 2.7, новые строки должны быть включены. –

ответ

17

Вам нужен tempered greedy token:

abc(?:(?!abc|xyz|123).)*123(?:(?!abc|xyz).)*xyz 

См. regex demo

Чтобы убедиться, что оно совпадает между строками, используйте флаг re.DOTALL при компиляции регулярного выражения.

Обратите внимание, что для достижения лучшей производительности с таким тяжелым рисунком вы должны рассмотреть возможность его разворачивания. Это можно сделать с помощью отрицательных классов символов и негативных обращений.Подробнее

Pattern:

  • abc - матч abc
  • (?:(?!abc|xyz|123).)* - соответствует любому символу, который не является отправной точкой для abc, xyz или 123 последовательности символов
  • 123 - символьной строки 123
  • (?:(?!abc|xyz).)* - любой символ, который не является отправной точкой для символа abc или xyz последовательности
  • xyz - косой подстроки xyz

Смотрите диаграмму ниже (если re.S используется, . будет означать AnyChar):

enter image description here

Смотрите Python demo:

import re 
p = re.compile(r'abc(?:(?!abc|xyz|123).)*123(?:(?!abc|xyz).)*xyz', re.DOTALL) 
s = "abc 123 xyz\nabc abc 123 xyz\nabc text 123 xyz\nabc text xyz xyz" 
print(p.findall(s)) 
// => ['abc 123 xyz', 'abc 123 xyz', 'abc text 123 xyz'] 
+0

Не могли бы вы связать сайт с того места, где вы создали этот конечный автомат? Я знаю, что сайт существует с похожим пользовательским интерфейсом, но не может его найти. Извините за нерелевантный комментарий. Я скоро его удалю :) – rafid059

+2

См. Https://jex.im/regulex –

+0

Почему '| 123'? –

1

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

/^abc(?!.*abc).*123.*(?<!xyz.*)xyz$/g 

(я не проверял.)

2

comment по hvd вполне уместно, и это только дает пример. В SQL, например, я думаю, было бы понятнее сделать:

where val like 'abc%123%xyz' and 
     val not like 'abc%abc%' and 
     val not like '%xyz%xyz' 

Я представляю себе нечто подобное просто сделать в других средах.

1

Использование PCRE решение будет:

Это используя m флаг. Если вы хотите проверить только от начала и конца строки добавить ^ и $ в начале и в конце соответственно

abc(?!.*(abc|xyz).*123).*123(?!.*(abc|xyz).*xyz).*xyz 

Regular expression visualization

Debuggex Demo

Смежные вопросы