Вопрос:
Хорошо, поэтому у меня есть фраза “foo bar”, и я хочу найти все, НО “foo bar”.
Вот мой текст.
ipsum dolor foo bar Lorem ipsum dolor sit amet,
consectetur adipisicing elit, sed do
eiusmod tempor foo bar incididunt ut labore etdolore foo bar
Есть ли способ сделать это прямо в регулярном выражении? Мне не нужно идти и использовать строки и т.д. Я?
РЕЗУЛЬТАТ:
ПРИМЕЧАНИЕ. Я не могу сделать приятное выделение, но полужирный дает вам представление (хотя пробелы, которые были до и после, также были выбраны, но он разбивает жирный шрифт).
ipsum dolor foo bar Lorem ipsum dolor sit amet,
consectetur adipisicing elit, sed do
eiusmod tempor foo bar incididunt ut labore et
dolore foo bar
Предположим, что номенклатура PCRE.
ОБНОВЛЕНИЕ 7/29/2013: может быть лучше использовать функцию поиска и замены на выбранном вами языке, чтобы просто “удалить” фразы, которые вы не хотите, чтобы потом вы оставались с информацией, которую вы делаете хотите.
Лучший ответ:
попробовать
^(?!.*foo bar).*$
это должно выбрать каждую строку, которая не содержит “foo bar”. (?!= отрицательный просмотр)
Ответ №1
В общем случае, если foobar соответствует самому себе, то (?s:(?!foobar).)* соответствует любому, что не является foobar, в том числе вообще ничего.
Вы можете использовать это, чтобы найти строки, в которых нет foobar, например, используя
^(?:(?!foobar).)*$
Вы также можете использовать свои языки split() для разделения на foobar, который даст вам все части, которые не включают разделяемый шаблон.
Что касается отвратительных малоизвестных контрольных глаголов backtracking, таких как (*FAIL) и (*COMMIT), у меня еще не было случая использовать их в “не игрушечных программах”. Я считаю, что независимые подвыражения через (?>…) и притяжательные кванторы *+, ++, ?+ и т.д. Дают мне более чем достаточно веревки, так сказать.
Тем не менее, у меня есть один игрушечный пример использования (*FAIL) в этом ответе; это первое решение регулярных выражений. Причина его присутствия заключалась в том, что я хотел заставить механизм регулярных выражений отступить через все возможные перестановки; реальная цель состояла в том, чтобы просто подсчитать, сколько способов она пробовала.
Пожалуйста, поймите, что мои два регулярных выражения, а также множество, невероятно творческих ответов от других, предназначены для развлечения, языка в щеках. Тем не менее, можно многому научиться у них – один раз оправиться от шока. ☺
Ответ №2
“удалить все, кроме foo bar”, эквивалентно “найти только foo bar”, что PCRE позволяет довольно легко. И наоборот, “найти все, кроме foo bar” эквивалентно “найти и удалить только foo bar”. Таким образом, дополнение можно легко сделать из ваших инструментов.
Кроме того, у PCRE есть неприятная небольшая функция, известная как *FAIL, которая сразу же вызывает обратную связь, когда она встречается. Таким образом, я полагаю, что добавление чего-то типа (*COMMIT)foo bar(*FAIL) в ваше регулярное выражение могло бы помочь. Однако это не дружелюбно и не очень безопасно.
Ответ №3
Итак, вы хотите удалить все, кроме foo bar, используя функцию поиска UltraEdit “Advanced” (Perl-regex style). Самый простой способ сделать это – совместить все, но только захватить foo bar, например:
(?:(?!foo bar).)+(foo bar|$)
… и замените его на $1 или 1 (независимо от того, какой стиль принимает UltraEdit).
Я не использую UltraEdit, но в EditPadPro он преобразует это:
ipsum dolor foo bar Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor foo bar incididunt ut labore et dolore foo bar
… к этому:
foo bar foo bar foo bar
… это результат, который вы указали в своем исходном сообщении.
Ответ №4
Здесь: perl -pe ‘s{.*?(foo bar)?}{$1}g’ <text
Я хочу найти все, НО “foo bar”
Образцовый шаблон без использования подстановки на $1 (который можно использовать с пустой заменой, как в s {pattern} {})… не уверен, что это возможно. Вы должны были бы сожрать символы до foo bar, например. с .*?(?=foo bar). Но тогда алгоритм совпадения продолжается и видит “oo bar” и будет совпадать снова, поскольку нет f.
Продолжая квест, вот фрагмент кода perl, который забирает запрошенные части, только с недостатком, что пустые записи могут быть возвращены, если foo bar находится в начале строки:
foreach (<>) { chomp; @_ = m{(.*?)(?:foo bar|$)}gs; print «[[ $_ ]]n» for @_; }
Нет никакого заместителя, и выполнение этого в файле теста Lorem ipsum покажет все, кроме частей foo bar. Он совместим с PCRE, но нет никаких гарантий того, что $EDITOR сделает то, что вы себе представляете.
Ответ №5
показать все, кроме “foo bar” и “fad bad”, это сработало для меня:
^(?!.*foo bar)(?!.*fad bad).*$