Регулярное выражение, которое не содержит определенную строку

У меня есть что-то вроде этого

aabbabcaabda

для выбора минимальной группы, обернутой a У меня есть этот /a([^a]*)a/, который отлично работает

Но у меня проблема с группами, обернутыми aa, где мне нужно что-то вроде /aa([^aa]*)aa/, который не работает, и я не могу использовать первый, например /aa([^a]*)aa/, потому что он закончится при первом входе a, который я не хочу.

Как правило, есть ли способ, как сказать не содержать строку так же, как Я могу сказать, что не содержит символ с [^a]?

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

Ответ 1

В общем, больно писать регулярное выражение not, содержащее определенную строку. Мы должны были сделать это для моделей вычислений - вы берете NFA, которую достаточно легко определить, а затем свести к регулярному выражению. Выражение для вещей, не содержащих "кошку", составляло около 80 символов.

Изменить: я только что закончил и да, это:

aa([^a] | a[^a])aa

Здесь - очень краткий учебник. Раньше я нашел несколько отличных, но я больше их не вижу.

Ответ 2

Пользуясь Google, я нашел blogpost от 2007, который дает следующее регулярное выражение, которое соответствует строке, которая не делает содержит определенную подстроку:

^((?!my string).)*$

Он работает следующим образом: он ищет нулевые или более (*) символы (.), которые не начинают (?! - negative lookahead) вашу строку, и в ней оговаривается, что вся строка должна состоять из таких символов (по используя якобы ^ и $). Или иначе:

Вся строка должна состоять из символов, которые не начинаются с заданной строки, а это означает, что строка не содержит заданную подстроку.

Ответ 3

Все, что вам нужно, - это неохотный квантификатор:

regex: /aa.*?aa/

aabbabcaabda   => aabbabcaa

aaaaaabda      => aaaa

aabbabcaabda   => aabbabcaa

aababaaaabdaa  => aababaa, aabdaa

Вы также можете использовать отрицательный lookahead, но в этом случае это всего лишь более верный способ выполнить одно и то же. Кроме того, это немного сложнее, чем gpojd сделал это. Смотритель должен применяться в каждой позиции до того, как точка будет иметь возможность использовать следующий символ.

/aa(?:(?!aa).)*aa/

Что касается подхода, предложенного Claudiu и finnw, он будет работать нормально, когда строка дозорного кода имеет всего два символа, но (как признал Клаудиу) это слишком громоздко для более длинных строк.

Ответ 4

/aa([^a]|a[^a])*aa/

Ответ 5

Я не уверен, что это стандартная конструкция, но я думаю, вам стоит взглянуть на "негативный взгляд" (который пишет: "?!", без кавычек). Это намного проще, чем все ответы в этом потоке, включая принятый.

Пример: Regex: "^ (?! 123) [0-9] *\w" Записывает любую строку, начинающуюся цифрами, за которой следуют буквы, ЕСЛИ если "эти цифры" 123.

http://msdn.microsoft.com/en-us/library/az24scfc%28v=vs.110%29.aspx#grouping_constructs (страница microsoft, но довольно полная) для lookahead/lookbehind

PS: он работает хорошо для меня (.Net). Но если я ошибаюсь, сообщите нам об этом. Я считаю, что эта конструкция очень проста и эффективна, поэтому я удивлен принятым ответом.

Ответ 6

Мне следующий код мне пришлось заменить, добавив GET-параметр ко всем ссылкам на JS файлы EXCEPT one.

<link rel="stylesheet" type="text/css" href="/login/css/ABC.css" />
<script type="text/javascript" language="javascript" src="/localization/DEF.js"></script>
<script type="text/javascript" language="javascript" src="/login/jslib/GHI.js"></script>
<script type="text/javascript" language="javascript" src="/login/jslib/md5.js"></script>
sendRequest('/application/srvc/EXCEPTION.js', handleChallengeResponse, null);
sendRequest('/application/srvc/EXCEPTION.js",handleChallengeResponse, null);

Используется для этого:

(?<!EXCEPTION)(\.js)

Что это значит - это поиск всех вхождений ".js", и если они предшествуют строке "EXCEPTION", отбросьте этот результат из массива результатов. Это называется негативным взглядом. Поскольку я потратил день на выяснение, как это сделать, я думал, что должен поделиться.

Ответ 7

".*[^(\\.inc)]\\.ftl$"

В Java это найдет все файлы, заканчивающиеся на ".ftl", но не заканчивающиеся на ".inc.ftl", что именно то, что я хотел.