2016-12-01 6 views
1

Предположим, что я хочу создать регулярное выражение, которое ищет два слова в строке, но с условием, что оно будет соответствовать только им, если между двумя ядром не будет одного из нескольких слов, м ищет. Например:Регулярное выражение с определенным условием

string input {"Somebody has typed in some words here."} 

Я ищу кого-то слова и слова, но я только хочу, чтобы регулярное выражение, чтобы соответствовать их, если есть не слово набирается где-то между ними (с типизированным быть только один из нескольких слова, которые я не хочу стоять между кем-то и словами). Какое регулярное выражение выполняет это? Я пробовал несколько подходов, но никто из них не работал так, как я предполагал. Может ли кто-нибудь помочь мне?

+1

Используйте [закаленное жадный маркер] (http://www.rexegg.com/regex-quantifiers.html#tempered_greed). –

ответ

2

Я хотел бы сделать это с помощью избегая с помощью regex, вызывают, как только вы ввести regex, Now you have 2 problems

Дано:

  1. Начало нашего диапазона поиска: const auto first = "Somebody"s
  2. Конец нашего поиска: const auto second = "words"s
  3. Сбор слов, которые не должны существовать в диапазоне: const vector<string> words = { "in"s }
  4. Входная строка: const auto input = "Somebody has typed in some words here."s

Мы можем сделать это:

const auto start = input.find(first) + size(first); 
const auto finish = input.find(second, start); 

if (start != string::npos && finish != string::npos) { 
    istringstream range(input.substr(start, finish - start)); 

    if (none_of(istream_iterator<string>(range), istream_iterator<string>(), [&](const auto& i) { return find(cbegin(words), cend(words), i) != cend(words); })) { 
     cout << "match\n"; 
    } else { 
     cout << "not a match\n"; 
    } 
} else { 
    cout << "not a match\n"; 
} 

Live Example


Если вы замужем за regex, хотя, есть способ, который вы можете сделать это, используя regex. Например, если words содержал: «в», «Lorem», и «Ipsum» вы хотите что-то вроде:

\bSomebody\b(?:(\bin\b|\blorem\b|\bipsum\b).*|.)*?\bwords\b

Тогда мы просто должны проверить, если наш матч содержал ничего:

const regex re("\\b" + first + accumulate(next(cbegin(words)), cend(words), "\\b(?:(\\b" + words.front(), [](const auto& lhs, const auto& rhs) { return lhs + "\\b|\\b" + rhs; }) + "\\b).*|.)*?\\b" + second + "\\b"); 
smatch sm; 

if (regex_search(input, sm, re) && sm[1].length() == 0U) { 
    cout << "match\n"; 
} else { 
    cout << "not a match\n"; 
} 

Live Example

+0

Это выглядит хорошо, хотя немного сложно для меня, как newby для понимания.Имеет ли это все это или его части имя, чтобы я мог сделать еще несколько исследований, чтобы лучше понять это? – AlexM

+0

Вы спрашиваете, есть ли у алгоритма имя? Naw, но все, что я использую, - это стандарт, чтобы вы могли выглядеть на http://en.cppreference.com, а живой пример очень полезен, если вы хотите возиться с вещами. Могу ли я ответить на конкретный вопрос? –

+0

Сначала я просматриваю вещи, которые для меня новы, а затем я вернусь сюда, чтобы понять, все ли понимаю, а если нет, я поставил бы здесь вопрос. Спасибо! – AlexM

0

Попробуйте следующее выражение: (somebody)(?!.*(?:typed|nice)).*(words). Он соответствует первому слову, за которым следует любое количество пробелов и второе слово. Матч останавливается после кого-то, если за ним следует любое количество символов и конкретных слов. Группа 1 соответствует словам кого-то и группе 2.

+0

Это не подходит, потому что (возможно, я не был достаточно точным в своем вопросе), это наличие или отсутствие конкретных слов в любой позиции между двумя словами, которые я ищу. Предположим, что я всегда хочу сопоставлять слова «кто-то» и «слова», если только слово не набрано, или слово «приятное» где-то между ними (типизировано и красиво - просто случайные примеры). Таким образом, выражение должно соответствовать предложению «Кто-то записал несколько слов», но не предложение «Кто-то написал хорошие слова» или предложение «Кто-то набрал слова». Это то, что я ищу. – AlexM

+0

См. Обновленный ответ –