Есть ли способ оглянуться назад и игнорировать конкретную букву в регулярном выражении? - PullRequest
2 голосов
/ 03 ноября 2019

Мне нужна помощь с регулярным выражением (Короче говоря, я создаю средство проверки грамматики для языка «папьяменто», языка, на котором говорят на островах АВС (карибский)), и некоторые слова могут быть сокращены, и яне знаю, как оглянуться назад и проигнорировать букву)

У меня есть слово «приди» (есть) и «есть» будет «comiendo». Видите, как «я» был добавлен между «м» и «е»? Я пытаюсь, чтобы мое регулярное выражение по-прежнему могло распознавать слово «приходить» с суффиксом «иэндо» и без него, проще всего было бы добавить группу без захвата (необязательно, я просто используюзахват группы для вещей, которые мне не нужны для захвата.) и проверка обоих по отдельности /com(?:iendo|e)?/, но я имею дело с более чем 16 тысячами слов, и неэффективно добавлять регулярное выражение для каждого отдельного слова в отдельности.

Мой вопрос таков: есть ли способ оглянуться назад и проигнорировать букву «е»?

/(come((?<=e)iendo))/, но при этом игнорировать «е», это регулярное выражение проверяет только на «come "and" comeiendo "(что неверно)


Чтобы быть немного яснее, у меня есть string[] со всеми словами, давайте использовать этот массив, например { "come", "bisti", "pasa" }, ониВсе глаголы в своей инфинитивной форме. Я хочу, чтобы регулярное выражение могло обнаружить его в бесконечной форме и форме, в которой выполняется действие (герунд). «приход» - это глагол в его инфинитивной форме, а «комьендо» - это герунд.

в моем регулярном выражении у меня это

string[] words = { "come", "bisti", "pasa" };
string pattern = $@"/({string.Join("|", words)})/";

// which is same as:
string pattern = @"/(come|bisti|pasa)/";

, но он проверяет только инфинитивную форму,в большинстве случаев герунда оканчивается на «ando» или «iendo» в зависимости от последней буквы глагола. Но в этом случае я хочу сосредоточиться только на «прийти» и «comiendo», потому что это единственная, которая заменяет последнюю букву (то есть «е») на «iendo», (другие глаголы просто добавляют «ndo» кконец).

поэтому с регулярным выражением я могу думать только о том, чтобы посмотреть, заканчивается ли глагол «е», затем проигнорировать «е» и проверить глагол (без «е»). ("com"), плюс суффикс ("iendo").

"come" => "com" + "iendo"

и это насколько я могу получить

string[] words = { "come", "bisti", "pasa" };
string pattern = $@"/((?:{string.Join("|", words)})(?:(?<=e)iendo|(?<=a)ndo)?)/";

// which is same as
string pattern = @"/((?:come|bisti|pasa)(?:(?<=e)iendo|(?<=a)ndo)?)/";

но это регулярное выражение работает только для "comeiendo", а не для "comiendo"

enter image description here

1 Ответ

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

У вас должна быть база данных, включающая все инфинитивные глаголы (индексированный столбец). Если в языке нет исключений (понимаете: вы всегда удаляете только последнюю букву, чтобы получить корень), тогда достаточно бесконечной формы. В противном случае в базе данных вам понадобится еще один столбец для определения корня слова. Альтернатива: используйте корневую форму в качестве ключа. Добавьте все полезные сопряженные формы в новые столбцы, если есть языковые исключения.

Используя простое регулярное выражение, которое обнаруживает инфинитивы и другие сопряженные формы, вы можете проверить для каждого совпадения, что это действительно глагол, а не ложный положительный результат.

«Comiendo» будет ложно-положительным, поскольку ни у одного глагола в базе данных этот ключ не будет.

/(\w*ndo\b|\w*a\b|\w*i\b|\w*e\b)/gm

Matching example С учетом объема слов взнаете, это правда, что это не хороший выбор, чтобы использовать все из них в регулярном выражении, а скорее использовать базу данных для проверки во второй раз, это сделано для того, я думаю: простой выбор будет быстрым наочень большой объем данных.

        var wordsFinder = new Regex(@"(\w*ndo\b|\w*a\b|\w*i\b|\w*e\b)", RegexOptions.Multiline | RegexOptions.IgnoreCase);

        foreach (Match match in wordsFinder.Matches(inputText))
        {
            var word = match.Value.ToLower();
            string infinitiveForm = null;
            if (word.EndsWith("iendo"))
                infinitiveForm = $"{word.Substring(0, word.Length - "iendo".Length)}e"; // not tested, please adapt :)
            else if (word.EndsWith("ando"))
                infinitiveForm = $"{word.Substring(0, word.Length - "ando".Length)}a";
            else
                infinitiveForm = word;

            // now check for infinitiveForm in the database
        }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...