и думать, что прошло 7 лет с тех пор, как вопрос был задан.

оторых разновидностях регулярных выражений [отрицательные] утверждения нулевой ширины (упреждающий просмотр / обратный просмотр) не поддерживаются.

Это делает чрезвычайно трудным (невозможным?) Утверждение исключения. Например, "каждая строка, котораяне есть "foo" на нем ", вот так:

^((?!foo).)*$

Можно ли добиться того же самого, не прибегая к осмотру вообще (на данный момент проблемы сложности и производительности не рассматриваются)?

 Tomalak09 февр. 2010 г., 15:07
@finnw: Хорошо, спасибо.
 finnw09 февр. 2010 г., 13:59
Нажмите на тег «regex-negation», чтобы увидеть похожие вопросы.

Ответы на вопрос(4)

улярному выражению из клиентского кода.

Для простого примера, допустим, вы хотите проверить, что строка содержит только определенные символы.

Вы можете написать это так:

^[A-Za-z0-9.$-]*$

и принятьtrue результат как действительный, или как это:

[^A-Za-z0-9.$-]

и принятьfalse результат действителен.

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

 21 янв. 2009 г., 18:03
Я знаю, что постобработка решит проблему ... Это то, чего я пытался избежать, я искал ванильное регулярное выражение, которое делает правильные вещи. Кроме того, я ищу что-то, что запрещает определенную последовательность символов, а не неупорядоченный набор.

что не было полностью работающего регулярного выражения, как личный вызов. Я считаю, что мне удалось создать регулярное выражение, котороеделает работать для всех входов - при условии, что вы можете использоватьатомная группировка/притяжательные квантификаторы.

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

\A(?:$|[^f]++|f++(?:[^o]|$)|(?:f++o)*+(?:[^o]|$))*\Z

Объяснение:

\A                         #Start of string
(?:                        #Non-capturing group
    $                      #Consume end-of-line. We're not in foo-mode.
    |[^f]++                #Consume every non-'f'. We're not in foo-mode.
    |f++(?:[^o]|$)          #Enter foo-mode with an 'f'. Consume all 'f's, but only exit foo-mode if 'o' is not the next character. Thus, 'f' is valid but 'fo' is invalid.
    |(?:f++o)*+(?:[^o]|$)  #Enter foo-mode with an 'f'. Consume all 'f's, followed by a single 'o'. Repeat, since '(f+o)*' by itself cannot contain 'foo'. Only exit foo-mode if 'o' is not the next character following (f+o). Thus, 'fo' is valid but 'foo' is invalid.
)*                         #Repeat the non-capturing group
\Z                         #End of string. Note that this regex only works in flavours that can match $\Z

Если по какой-либо причине вы можете использовать атомарную группировку, но не собственнические квантификаторы или обходные пути, вы можете использовать:

\A(?:$|(?>[^f]+)|(?>f+)(?:[^o]|$)|(?>(?:(?>f+)o)*)(?:[^o]|$))*\Z

Однако, как отмечают другие, возможно, более практично просто отрицать совпадение другими способами.

 jaytea09 сент. 2018 г., 16:50
На самом деле можно выразить^(?!.*foo) без каких-либо расширенных функций регулярных выражений: D Решение в этом случае:^([^f]|(f+o)*f+([^fo]|o([^fo]|$)|$))*$, Мы можем даже довольно элегантно расширить это на любую произвольную подстроку "foo" ... Я скоро опубликую подробный обзор об этом!
Решение Вопроса

ОБНОВИТЬ: Это терпит неудачу "с двумя ff перед oo" как@Ciantic указал в комментариях.

НОТА: Гораздо проще просто отрицать совпадение на стороне клиента, чем использовать приведенное выше регулярное выражение.

Регулярное выражение предполагает, что каждая строка заканчивается символом новой строки, если это не так, то смотрите регулярные выражения C ++ и grep.

Примеры программ на Perl, Python, C ++ иgrep все дают одинаковый вывод.

Perl

#!/usr/bin/perl -wn
print if //;

питон

#!/usr/bin/env python
import fileinput, re, sys
from itertools import ifilter

re_not_foo = re.compile(r"")
for line in ifilter(re_not_foo.match, fileinput.input()):
    sys.stdout.write(line)

C ++

#include <iostream>
#include <string>
#include <boost/regex.hpp>

int main()
{
  boost::regex re("^(f(o([^o]|$)|([^o]|$))|[^f])*$");
  //NOTE: "|$"s are there due to `getline()` strips newline char

  std::string line;
  while (std::getline(std::cin, line)) 
    if (boost::regex_match(line, re))
      std::cout << line << std::endl;
}

Grep

$ grep "^\(f\(o\([^o]\|$\)\|\([^o]\|$\)\)\|[^f]\)*$" in.txt

Образец файла:

foo
'foo'
abdfoode
abdfode
abdfde
abcde
f

fo
foo
fooo
ofooa
ofo
ofoo

Выход:

abdfode
abdfde
abcde
f

fo
ofo
 Gumbo21 янв. 2009 г., 19:20
Приятно. Действительно, очень мило.
 Tomalak21 янв. 2009 г., 19:26
Понятно, что постобработка в программе, отрицание соответствия, является предпочтительным методом. Иногда у вас нет выбора, и даже если у вас есть, это хорошо, чтобы знать ваши альтернативы.
 Gumbo08 февр. 2010 г., 15:38
@ J.F. Себастьян: Ах, ты прав. Интересно, почему он не изменил другие?
 Gumbo07 февр. 2010 г., 21:04
Это регулярное выражение не правильно. Это не совпадаетf, fo или жеbarf, Но этот делает:^(f(o([^o]|$)|[^o]|$)|[^f])*$
 Ciantic24 окт. 2017 г., 13:31
Ответ, похоже, не работает сsomethingffoosomething с двумя фф перед оо.

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

Моя первоначальная реакция на эту ситуацию:Например, «каждая строка, в которой нет« foo »» было просто использовать опцию -v invert смысл соответствия в grep.

grep -v foo

это возвращает все строки в файле, которые не соответствуют 'foo'

У меня такое сильное чувство, что я просто неправильно понял твой вопрос ...

 Alan Moore07 авг. 2009 г., 06:01
grep -v foo ищет «foo» и отрицает результат, а ОП говорит, что хочет, чтобы само регулярное выражение выполняло эту работу. Но предположим, что требование "содержит" foo "ине содержать 'bar' ", и вы можете выполнить только одно совпадение с регулярным выражением? Просто отрицание результата не будет возможным.
 Alan Moore15 окт. 2011 г., 08:06
@ZacharyYoung: конечноgrep -v или эквивалентный - лучший способ пойти, если доступно. Но ОП говорил о гипотетической ситуации, когда выне может переверните матч и выне может использовать взгляды К счастью, подобные ситуации крайне редки в реальном мире. ;)
 Dmitry Grigoryev14 мар. 2016 г., 12:43
@AlanMoore вы говорите крайне редко? Вотодини думать, что прошло 7 лет с тех пор, как вопрос был задан.
 Zachary Young15 окт. 2011 г., 01:48
@Alan: Верно, но почему (на первый взгляд) произвольный лимит в одно регулярное выражение? Если мы не ограничены одним совпадением, мы можем выполнить конвейер:grep foo <file> | grep -v bar, Я поднял этот вопрос, потому что я не мог понять вышеприведенные примеры и заставить их работать в Emacs, но смог сделать это только из командной строки.

Ваш ответ на вопрос