| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Java: Общие вопросы > Как делается отрицание слова |
| Автор: _program_seeker 28.2.2007, 14:54 | ||
| Здравствуйте, я прочитал про регулярные выражения, поделал некоторые примеры, но более сложные вещи осуществить трудно и непонятно. Помогите пожалуйста составить регулярное выражение, кторое описывает строку, содержащую любые последовательнсти символов кроме указанной цепочки. Использую следующий паттерн
все работает как надо: nnABnnnnnnnnnnABnnnn - здесь выводит true, потому что строка содержит обрамление AB nnnnnnnnnnnnnnnnnnnnnn - здесь выводит false, потому что обрамления нет nnABnnnnnAnnnnnABnn - здесь выводит false, потому что внутри обрамления есть запрещенный символ A вот... а мне теперь нужно чтобы был не просто запрещенный символ A а запрещенная цепочка AB. и всвязи с этим возникло затруднение.. как указать в паттерне отрицание слова AB ? |
| Автор: DEER 28.2.2007, 15:42 |
| AB([^(AB)]*)AB |
| Автор: _program_seeker 28.2.2007, 15:52 |
| к сожалению паттерн AB([^(AB)]*)AB реагирует и на такую строку ABnnnnnAnnnnnnnnnnnnnnnnnAB |
| Автор: DEER 28.2.2007, 16:08 |
| ну да... там же нет AB в середине строки.. а ловятся только AB целиком если надо не A и не B, то AB([^AB]*)AB |
| Автор: w1nd 28.2.2007, 16:15 |
| AB([^\\QAB\\E]*)AB И [^AB], и [^(AB)] означает "не (A или B)". |
| Автор: _program_seeker 28.2.2007, 17:31 | ||
так тоже не работает... кроме того иногда вылетают непонятные исключения... ладно - может просто переформулировать задачу, чтобы было более понятно: как найти строки, не содержащие слово водка? например: "это простое предложение про огурец" - эта строка правильная "водка это напиток богов" - эта строка неправильная |
| Автор: nornad 28.2.2007, 17:48 | ||
| Вообще-то, и AB([^\\QAB\\E]*)AB тоже означает не (А или В) - в классе символов описываются символы, а не последовательности. Специально проверил ваш шаблон:
Разница в строках всего в один символ. Добавлено @ 17:50 Если инвертировать подход к решению, то задача решается проще некуда. Просто найди все строки, которые содержат запрещённые слова. |
| Автор: _program_seeker 28.2.2007, 18:04 | ||
ну а прямого решения выходит не существует? |
| Автор: nornad 28.2.2007, 18:25 |
| Не могу гарантировать на 100%, но я не знаю, как можно организовать отрицание некоторой последовательности. |
| Автор: _program_seeker 28.2.2007, 18:31 | ||
всем откликнувшимся большое спасибо за участие! ваши примеры помогли мне и навели на такое решение! которое по моему делает то что мне надо:
буду тестировать нет ли тут подводных камней |
| Автор: DEER 28.2.2007, 18:34 |
| млин точно! |
| Автор: _program_seeker 28.2.2007, 18:52 |
| только как я и предполагал, тут обнаружился неприятный подводный камень: паттерн: AB([^A][^B]*?)AB строка: ABoooooooooooooooooAB результат: соответствует шаблону строка: ABoooooooABooooooooooAB результат: несоответствует шаблону и вот он подводный камень! строка: ABoooooooAooBooooooooooAB результат: несоответствует шаблону (хотя по задумке должен) и вот камень строка: ABoooooooBAooooooooooAB результат: несоответствует шаблону (просто поменяли местами A и B) |
| Автор: nornad 28.2.2007, 19:41 |
| Даже ABoooooooAooooooooooAB будет с "камнем". Потому что шаблон означает следующее: "проверить, начинается ли строка с АВ, заканчивается ли АВ и при этом не содержит ни А, ни В внутри". |
| Автор: w1nd 28.2.2007, 23:24 |
Правильно, это означает "не AB". И отлично работает для "ABoooooooooooooooooAB", "ABoooooooAooBooooooooooAB" и "ABoooooooBAooooooooooAB". Строка "ABoooooooABooooooooooAB", разумеется, не подходит, так как содержит "AB". А вот шаблон "AB([^A][^B]*?)AB" неверен (если исходить из первоначальных условий), потому что последовательность "[^A][^B]" означает "любые два символа не являющиеся A или B". А слово водка в предложении найдет вот такой шаблон: ".*\\QВОДКА\\E.*" |
| Автор: nornad 28.2.2007, 23:38 | ||
Уверен? Проверял? Вот что говорит тестирование шаблона AB([^\\QAB\\E]*)AB на приведённых строках:
Может, суть задачи не до конца ясна? Надо проверить строку на то, что в ней не содержится непрерывная последовательность АВ, а не просто два символа А и В. Причём, я бы в шаблон добавил ^$, иначе сами видите, что получается (последняя строка в примере). |
| Автор: nornad 1.3.2007, 01:55 | ||
Странно... У меня твой пример даёт такой вот результат:
Проверял на jdk6.0 Добавлено @ 01:57 По идее, внутри [] по правилам регулярных выражений указывается символьный класс, соответствующий одному символу. Не представляю, как у тебя твой пример смог обработать символьный класс как последовательность... |
| Автор: corpsehunter 1.3.2007, 02:49 | ||
Ничего странного, у меня такой же Вообще, выражение [^\\QAB\\E] значит любой из символов, кроме \ Q A B \ E |
| Автор: nornad 1.3.2007, 04:34 | ||||
Конечно. Скомпилирую в жабе простейший исходник:
И посмотри, что тебе скажет жаба. ;) Добавлено @ 04:42 corpsehunter, кстати, я не совсем понял, что ты хотел сказать словами
Это ты мне объяснял или w1nd'у? \QAB\E - любая последовательность не АВ [\QAB\E] - любой один символ, кроме А и В. А мои слова относились к тому, что я не понимаю, каким образом на jdk1.5.0_01 это дело работало не как символьный класс, а как последовательность. Добавлено @ 04:45 Всё, дошло, что ты имел в виду. Если ты заметил, в коде [^\\QAB\\E] взято в кавычки. |
| Автор: w1nd 1.3.2007, 13:08 | ||
Да, с символьным типом я обмишурился. Значит в пятёрке баг в реализации regexp... |
| Автор: corpsehunter 1.3.2007, 15:10 | ||||
Т.е. это тоже самое, что и [^A][^B]?
А это - [^AB]? Просто в первом примере стоял двойной бэкслэш, а это в регулярном выражении значит одинарный слэш, а тут ты уже поставил одинарный Да и вообще, я раньше не слышал про \Q...\E, шаз прочитал в доке - там написано, что все, что заключено в них просто экранируется бэкслэшем. Че-то несостыковочка какая-то... |
| Автор: _program_seeker 1.3.2007, 17:34 | ||||||
| w1nd, спасибо, твой пример я проверил на свежую голову и действительно все работает! я немного изменил только твою программу, и добавил пару тестовых строк, и вот что получилось: программа (jdk_1.5.0_8):
я добавил переменную t для того чтобы можно было обрамлять строки теста дополнительными незначащими символами, для чего это сделано - будет видно чуть позже. Вначале я провел тест при значении переменной t = "", и вот результаты:
на этом наборе тестов паттерн, предложенный w1nd, работает превосходно. а вот когда я провел тесты но при значении переменной t = "oo" то получил результаты которые не поддаются логике:
почему так? ведь паттерн не ограничивается строкой, в нем нет начального ^ и завершающего $ символа? |
| Автор: nornad 1.3.2007, 18:04 | ||||
Нет. [^A][^B] - два последовательных символа, но первый не А, а второй не В. \QAB\E - последовательность любой величины, лишь бы это не была последовательность АВ.
Да.
Потому что String.matches работает не совсем так, как обычный паттерн-матчинг. Часто он считает, что твой шаблон должен подходить именно для всей строки. Я бы сказал, что это всегда так, но сам пару раз столкнулся с необходимостью явно указать ^$. Кстати, раз уж ты пишешь в пятой жабе, то учти, что этот же код в шестой жабе уже будет работать иначе. О причине читай выше. Добавлено @ 18:06 Хотя, насчёт \QAB\E могу ошибаться - мало сталкивался. |
| Автор: corpsehunter 1.3.2007, 18:24 | ||
| У меня в первом случае все равно не так получается. Во втором так же. Версия 1.6.0 И вообще, не понимаю, почему у тебя так получается и откуда взяли, что \Q…\E обозначает последовательность:
P.S. Со количеством слэшэй я накосячил - перепутал с пхп - там используется одиночный... |
| Автор: nornad 1.3.2007, 21:50 |
| Спасибо, что напомнил. Итого получаем, что \QАВ\E === АВ, а [^\QАВ\E] === [^АВ]. |
| Автор: sova7 2.3.2007, 11:24 | ||
| Насчет поиска фраз "без слова водка" - так понял, решение не найдено ? Из решений обратной задачи для "ABooAooBooAB" можно предложить
|