Regex для анализа значений строки запроса в именованных группах - PullRequest
1 голос
/ 24 ноября 2008

У меня есть HTML со следующим содержанием:

... some text ...
<a href="file.aspx?userId=123&section=2">link</a> ... some text ...
... some text ...
<a href="file.aspx?section=5&user=678">link</a> ... some text ...
... some text ...

Я хотел бы проанализировать это и получить соответствие с именованными группами:

соответствует 1

Группа [ "пользователь"] = 123

Группа [ "раздел"] = 2

совпадение 2

группа [ "пользователь"] = 678

группа [ "раздел"] = 5

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

Спасибо!

Ответы [ 9 ]

8 голосов
/ 13 января 2012

В моем случае мне пришлось проанализировать URL-адрес, поскольку утилита HttpUtility.ParseQueryString недоступна в WP7. Итак, я создал такой метод расширения:

public static class UriExtensions
{
    private static readonly Regex queryStringRegex;
    static UriExtensions()
    {
        queryStringRegex = new Regex(@"[\?&](?<name>[^&=]+)=(?<value>[^&=]+)");
    }

    public static IEnumerable<KeyValuePair<string, string>> ParseQueryString(this Uri uri)
    {
        if (uri == null)
            throw new ArgumentException("uri");

        var matches = queryStringRegex.Matches(uri.OriginalString);
        for (int i = 0; i < matches.Count; i++)
        {
            var match = matches[i];
            yield return new KeyValuePair<string, string>(match.Groups["name"].Value, match.Groups["value"].Value);
        }
    }
}

Тогда это вопрос использования, например

        var uri = new Uri(HttpUtility.UrlDecode(@"file.aspx?userId=123&section=2"),UriKind.RelativeOrAbsolute);
        var parameters = uri.ParseQueryString().ToDictionary( kvp => kvp.Key, kvp => kvp.Value);
        var userId = parameters["userId"];
        var section = parameters["section"];

ПРИМЕЧАНИЕ: Я возвращаю IEnumerable вместо словаря напрямую только потому, что предполагаю, что может быть дублированное имя параметра. Если есть дублированные имена, то словарь выдаст исключение.

5 голосов
/ 24 ноября 2008

Зачем использовать регулярные выражения, чтобы разделить его?

Вы можете сначала извлечь строку запроса. Разделите результат на &, а затем создайте карту, разделив результат с этого на =

1 голос
/ 24 ноября 2008

Вы не указали, на каком языке вы работаете, но это должно сработать в C #:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace RegexTest
{
    class Program
    {
        static void Main(string[] args)
        {
            string subjectString = @"... some text ...
                <a href=""file.aspx?userId=123&section=2"">link</a> ... some text ...
... some text ...
<a href=""file.aspx?section=5&user=678"">link</a> ... some text ...
... some text ...";
            Regex regexObj = 
               new Regex(@"<a href=""file.aspx\?(?:(?:userId=(?<user>.+?)&section=(?<section>.+?)"")|(?:section=(?<section>.+?)&user=(?<user>.+?)""))");
            Match matchResults = regexObj.Match(subjectString);
            while (matchResults.Success)
            {
                string user = matchResults.Groups["user"].Value;
                string section = matchResults.Groups["section"].Value;
                Console.WriteLine(string.Format("User = {0}, Section = {1}", user, section));
                matchResults = matchResults.NextMatch();
            }
            Console.ReadKey();
        }
    }
}
0 голосов
/ 24 ноября 2008

простая реализация Python, преодолевающая проблему упорядочения

In [2]: x = re.compile('(?:(userId|section)=(\d+))+')

In [3]: t = 'href="file.aspx?section=2&userId=123"'

In [4]: x.findall(t)
Out[4]: [('section', '2'), ('userId', '123')]

In [5]: t = 'href="file.aspx?userId=123&section=2"'

In [6]: x.findall(t)
Out[6]: [('userId', '123'), ('section', '2')]
0 голосов
/ 24 ноября 2008

Вы не сказали, какой тип регулярного выражения вы используете. Так как ваш пример URL ссылается на файл .aspx, я предполагаю .NET. В .NET одно регулярное выражение может иметь несколько именованных групп захвата с одинаковым именем, и .NET будет обрабатывать их, как если бы они были одной группой. Таким образом, вы можете использовать регулярное выражение

userID=(?<user>\d+)&section=(?<section>\d+)|section=(?<section>\d+)&userID=(?<user>\d+)

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

0 голосов
/ 24 ноября 2008

Другой подход заключается в размещении групп захвата внутри перспектив:

Regex r = new Regex(@"<a href=""file\.aspx\?" +
                    @"(?=[^""<>]*?user=(?<user>\w+))" +
                    @"(?=[^""<>]*?section=(?<section>\w+))";

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

Кстати, вопреки вашему ответу Клаусу, совершенно неважно, на каком языке вы работаете. Существуют огромные различия в возможностях, синтаксисе и API от одного языка к другому.

0 голосов
/ 24 ноября 2008

Возможно, что-то вроде этого (я ржавый в регулярных выражениях, и в любом случае я не был хорош в них. Непроверенный):

/href="[^?]*([?&](userId=(?<user>\d+))|section=(?<section>\d+))*"/

(Кстати, XHTML искажен; & должно быть & amp; в атрибутах.)

0 голосов
/ 24 ноября 2008

Проверьте это

\<a\s+href\s*=\s*["'](?<baseUri>.+?)\?(?:(?<key>.+?)=(?<value>.+?)[&"'])*\s*\>

Вы можете получить пары с чем-то вроде Groups ["key"]. Captures [i] и Groups ["value"]. Captures [i]

0 голосов
/ 24 ноября 2008

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

Я заинтересован в полном решении регулярных выражений.

Любой

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