Соответствие регулярному выражению, но игнорирует определенные символы в выводе

1

Мне нужно регулярное выражение PATTERN (для использования в С#), которое будет соответствовать целочисленным значениям с 3-значными разделителями запятой, но НЕ будет возвращать запятые в полученное значение соответствия. Например, мне нужен следующий код для записи 1, 1234 и 1234567 на консоль:

string text = "This 1 is 1,234 a 1,234,567 sentence 7,654.321.";
// NOTE: value "7,654.321" would preferably NOT match, 
//       but it is acceptable for now if it does
MatchCollection matches = Regex.Matches(text, PATTERN);
foreach (Match match in matches)
    Console.Write(match.Value + " ");

Я НЕ МОЖЕТ вызвать Regex.Matches а затем сделать String.Replace чтобы удалить запятые; все это должно произойти в регулярном выражении PATTERN (потому что все мои выражения регулярных выражений извлекаются из базы данных и не могут включать логику вне самого шаблона без большого количества кода спагетти). Как уже отмечалось, я бы предпочел не сопоставлять рациональные ценности, но это должно быть легко исправить, если я получу отключение запятой.

Следующий шаблон НЕ РАБОТАЕТ, но он, вероятно, очень близок к тому, что мне нужно:

// THIS PATTEN DOES NOT WORK!!!
//    but is probably close to what I need
string PATTERN = @"([\+-]?[0-9]+[(?<=,)[0,9]{3}]*)([eE][\+]?[0-9]+)?"

Если вы удалите [(?<=,)[0,9]{3}]* сверху, у вас есть стандартный целочисленный шаблон. Еще раз, мне нужно принять запятые в целое число, но не возвращать их как часть совпадения. Как мне изменить этот шаблон?

  • 1
    msgstr "сопоставлять целочисленные значения с 3-значными разделителями запятых, но НЕ возвращать запятые в результирующем значении соответствия" ..RegEx не может этого сделать. Это соответствует слева направо .. и что соответствует, соответствует. Вы можете захватить каждый набор из 1-3 цифр для каждого совпадения, но было бы проще просто получить совпадение и заменить все запятые пустыми строками.
  • 0
    Вы можете использовать Regex.Replace(String, MatchEvaluator) . Просто сопоставьте что-то вроде (?:^|(?<=\s))\d{1,3}(?:,\d{3})*(?!\.\d) и удалите запятые в функции ,
Теги:
string-parsing

1 ответ

0

Соответствие регулярных выражений представляет собой целую подстроку входной строки. Это не может быть набор подстрок - это должна быть одна подстрока.

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

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

Во-первых, регулярное выражение. Он упрощен до минимума, так что его легче понять:

(?:(?<concat>\d+),?)+

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

Затем в вашем коде вы можете реализовать следующую логику:

  • Если регулярное выражение не содержит группу с именем concat, тогда процесс как обычно
  • Если это так, сделайте следующее, а не получите весь матч:
    • Извлеките все записи этой группы: match.Groups["concat"].Captures
    • Сопоставьте полученные значения
    • И затем используйте это значение

Это было бы похоже на это:

public static IEnumerable<string> GetValues(string input)
{
    // Suppose regex could be any regex
    var regex = new Regex(@"(?:(?<concat>\d+),?)+");

    foreach (Match match in regex.Matches(input))
    {
        // Does this regex have our special feature?
        if (regex.GroupNumberFromName("concat") >= 0)
        {
            // Concat the captured values
            var captures = match.Groups["concat"].Captures.Cast<Capture>().Select(c => c.Value).ToArray();
            yield return String.Concat(captures);
        }
        else
        {
            // This is a normal regex
            yield return match.Value;   
        }
    }
}

Идеальная демонстрация

Хорошо, это взломать, но это позволит вам сохранить логику декларативным и многоразовым способом в регулярном выражении.

Теперь полное regex, которое вы разместили, будет выглядеть примерно так в своей взломанной версии:

(?<concat>[-+])?(?<concat>[0-9]+)(?:,(?<concat>[0-9]{3}))*(?<concat>[eE][-+]?[0-9]+)?

демонстрация

Ещё вопросы

Сообщество Overcoder
Наверх
Меню