Регулярное выражение, которое возвращает постоянное значение как часть соответствия - PullRequest
3 голосов
/ 13 февраля 2009

У меня есть регулярное выражение, соответствующее двум различным числовым форматам: \ = (? [0-9] +) \? | \ + (? [0-9] +) \?

Это должно вернуть 9876543 как его значение для ; 1234567890123456? + 1234567890123456789012345123 = 9876543?
и ; 1234567890123456? +9876543? Я хотел бы иметь возможность возвращать другое значение вместе с совпадающим значением.

Так, например, если первая строка была найдена, я бы хотел, чтобы она возвращала:

Значение: 9876543 Формат: LongFormat


А если сопоставляется во второй строке:

Значение: 9876543 Формат: ShortFormat


Возможно ли это?

Ответы [ 3 ]

3 голосов
/ 15 февраля 2009

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

Вот немного C #:

var regex = new Regex(@"\=(?<Long>[0-9]+)\?|\+(?<Short>[0-9]+)\?");
string test1 = ";1234567890123456?+1234567890123456789012345123=9876543?";
string test2 = ";1234567890123456?+9876543?";

var match = regex.Match(test1);
Console.WriteLine("Long: {0}", match.Groups["Long"]);     // 9876543
Console.WriteLine("Short: {0}", match.Groups["Short"]);   // blank
match = regex.Match(test2);
Console.WriteLine("Long: {0}", match.Groups["Long"]);     // blank
Console.WriteLine("Short: {0}", match.Groups["Short"]);   // 9876543

По сути, просто измените свое регулярное выражение, включив в него имена, и затем регулярное выражение. У групп [GroupName] будет либо значение, либо значение. Вы можете даже использовать свойство Success группы, чтобы узнать, какие из них совпадают (match.Groups ["Long"]. Success).

UPDATE: Вы можете получить название группы вне соответствия со следующим кодом:

static void Main(string[] args)
{
    var regex = new Regex(@"\=(?<Long>[0-9]+)\?|\+(?<Short>[0-9]+)\?");
    string test1 = ";1234567890123456?+1234567890123456789012345123=9876543?";
    string test2 = ";1234567890123456?+9876543?";

    ShowGroupMatches(regex, test1);
    ShowGroupMatches(regex, test2);
    Console.ReadLine();
}

private static void ShowGroupMatches(Regex regex, string testCase)
{
    int i = 0;
    foreach (Group grp in regex.Match(testCase).Groups)
    {
        if (grp.Success && i != 0)
        {
            Console.WriteLine(regex.GroupNameFromNumber(i) + " : " + grp.Value);
        }
        i++;
    }
}

Я игнорирую 0-ую группу, потому что это всегда полное совпадение в .NET

2 голосов
/ 13 февраля 2009

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

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

if match(\=(?[0-9]+)\?) then
    return 'Value: ' + match + 'Format: LongFormat'
else if match(\+(?[0-9]+)\?) then
    return 'Value: ' + match + 'Format: ShortFormat'

(Извините за изворотливый псевдокод, но вы поняли.)

1 голос
/ 13 февраля 2009

Вы не можете сопоставить текст, которого там нет - но, в зависимости от того, какой язык вы используете, вы можете обработать того, что вам подходит, и условно добавить текст на основе того, что там есть. 1003 *

В некоторых реализациях регулярных выражений вы можете указать «функцию обратного вызова», которая позволяет запускать логику для каждого результата.

Вот пример псевдокода:

Input.replaceAll( /[+=][0-9]+(?=\?)/ , formatValue );

formatValue : function(match,groups)
{
    switch( left(match,1) )
    {
        case '+' : Format = 'Short';   break;
        case '=' : Format = 'Long';    break;
        default  : Format = 'Unknown'; break;
    }

    Value : match.replace('[+=]');

    return 'Value: '+Value+' Format: ' + Format;
}

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

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

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