2009-04-04 5 views
70

У меня есть что-то вроде этогоРегулярное выражение, которое не содержит определенную строку

aabbabcaabda

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

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

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

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

+0

@SteveChambers Вы понимаете, что этот вопрос старше 7 лет и уже имеет принятый ответ? –

+1

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

ответ

17

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

Edit: Я только что закончил, и да, это:

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

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

+0

Знаете ли вы, какой учебник объясняет это? –

+0

Здесь есть хорошее учебное пособие по регулярному выражению: http://www.regular-expressions.info/ –

+0

Привет, вы уверены в этом? Может кто-нибудь сказать нам, если что-то не так с моим ответом: http://stackoverflow.com/a/27060278/461444 – AFract

10

Все, что вам нужно, это неохотно квантор:

regex: /aa.*?aa/ 

aabbabcaabda => aabbabcaa 

aaaaaabda  => aaaa 

aabbabcaabda => aabbabcaa 

aababaaaabdaa => aababaa, aabdaa 

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

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

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

+1

Я думаю, что наш путь - единственный метод, который будет работать с реализацией без обратного отслеживания (http: // swtch.com/~rsc/regexp/regexp1.html), но да, это ужасно раздражает. Я просто не знаю регулярное выражение достаточно хорошо, чтобы знать об этих взглядах =). – Claudiu

+0

Большинство современных ароматизаторов регулярных выражений, особенно тех, которые встроены в языки программирования, относятся к обратному типу, типу NFA. Даже JavaScript, один из наименее функциональных вкусов, поддерживает взгляды и неохотные кванторы. http://www.regular-expressions.info/refflavors.html –

186

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

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

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

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

+7

Согласно документам, это отрицательный взгляд, а не lookbehind –

+0

(из цитируемого блога) full regexp ref: http://www.regular-expressions.info /refadv.html –

+1

Точное решение для вопроса: '^ aa (?!. * aa. * aa). * aa $' ie start by ** aa **, смотреть вперёд и отменить выбор, который следует за ** [ничего] aa [ничего] aa ** и закончить ** aa ** –

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

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

+2

'[]' split 'inc' в' i', 'n',' c'. Таким образом, это неверно как с "aiftl" .matches (". * [^ (\\. Inc)] \\. Ftl $") 'и' "a.inc.ftl" .matches (". * [^(\\. вкл)] \\. FTL $ ")'. – 2012-11-07 11:20:50

4

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

<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“ строка, отбросить этот результат из массив результатов. Это называется негативным взглядом. Поскольку я потратил день на выяснение, как это сделать, я думал, что должен поделиться.

6

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

Пример: Regex: "^ (?! 123) [0-9] * \ ш" захватывает любую строку, начинающуюся с помощью цифр, букв, после чего, если не указано, если "эти цифры" являются 123.

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

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

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