Совпадение не более n символов - PullRequest
0 голосов
/ 09 ноября 2019

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

((X:){1,6})((:Y){1,6})

X:X:X:X:X::Y:Y             This should match
X:X:X:X:X:X::Y:Y           This should not match.

https://regex101.com/r/zxfAB7/16

Есть ли способ сделать это? Мне нужна группа захвата $ 1 и $ 3
Я использую регулярное выражение C ++ 17.

Ответы [ 3 ]

1 голос
/ 09 ноября 2019

Если поддерживается положительный прогноз, вы можете использовать положительный прогноз, чтобы утверждать не 8 повторений X: или :Y.

Чтобы предотвратить пустое совпадение, вы можете использовать положительный прогноз, чтобы проверить, есть ли хотя бы 1 совпадение.

Затем используйте 2 группы захвата, где вы повторяете 0+ раз либо совпадение X: впервая группа a и 0+ раз совпадают с :Y в другой группе.

^(?=(?:X:|:Y))(?!(?:(?:X:|:Y)){8})((?:X:)*)((?::Y)*)$
  • ^ начало строки
  • (?= положительный взгляд вперед, утверждают, что являетсясправа
    • (?:X:|:Y) Соответствует либо X:, либо :Y
  • ) Закрыть положительный прогноз
  • (?! Отрицательныйсмотри вперед, утверждай, что 8 раз не соответствуют ни X:, ни :Y
    • (?:(?:X:|:Y)){8}
  • ) закрыть отрицательный прогноз
  • ((?:X:)*) Группа захвата 1 совпадение 0+ раз X:
  • ((?::Y)*) Группа захвата 2 совпадение 0+ раз :Y
  • $ Конец строки

Regex demo

0 голосов
/ 10 ноября 2019

Хотя уже есть принятый ответ, я хотел бы показать очень простое и простое решение. Протестировано с C ++ 17. И полный исходный код.

Поскольку речь идет о макс. 7 группах, мы можем просто перечислить их все и «или» их. Это может быть много текста и сложный DFA. Но это должно сработать.

После того, как мы нашли совпадение, мы определяем вектор, помещаем в него все данные / группы и показываем желаемый результат. Это действительно просто:

Пожалуйста, смотрите:

#include <iostream>
#include <string>
#include <iterator>
#include <vector>
#include <regex>

std::vector<std::string> test{
    "X::Y",
    "X:X::Y",
    "X:X::Y:Y",
    "X:X:X::Y:Y",
    "X::Y:Y:Y:Y:Y",
    "X:X:X:X:X::Y:Y",
    "X:X:X:X:X:X::Y:Y"
};

const std::regex re1{ R"((((X:){1,1}(:Y){1,6})|((X:){1,2}(:Y){1,5})|((X:){1,3}(:Y){1,4})|((X:){1,4}(:Y){1,3})|((X:){1,5}(:Y){1,2})|((X:){1,6}(:Y){1,1})))" };
const std::regex re2{ R"(((X:)|(:Y)))" };

int main() {
    std::smatch sm;
    // Go through all test strings
    for (const std::string s : test) {
        // Look for a match
        if (std::regex_match(s, sm, re1)) {
            // Show succes message
            std::cout << "Match found for  -->  " << s << "\n";
            // Get all data (groups) into a vector
            std::vector<std::string> data{ std::sregex_token_iterator(s.begin(), s.end(),re2,1),  std::sregex_token_iterator() };
            // Show desired groups
            if (data.size() >= 6) {
                std::cout << "Group 1: '" << data[0] << "'   Group 6: '" << data[5] << "'\n";
            }
        }
        else {
            std::cout << "**** NO match found for  -->  " << s << "\n";
        }
    }
    return 0;
}

0 голосов
/ 09 ноября 2019

Как уже упоминал Ульрих, простое использование регулярных выражений может не быть решением. Я бы посоветовал вам следующее:

Replace all X (occuring 1 to 6 times) by an empty string
Replace all Y (occuring 1 to 6 times) by an empty string
Use regex for determining if any X is still present
Use regex for determining if any Y is still present

В случае, если все X или Y появляются только от 1 до 6 раз, никаких X или Y не будет найдено (возврат match), иначе верните no match.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...