1

我有一个包含以下内容的 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

如果参数总是按顺序排列,首先是用户,然后是部分,我可以做到这一点,但如果顺序不同,我不知道该怎么做。

谢谢!

4

9 回答 9

8

在我的情况下,我必须解析一个 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 而不是字典,只是因为我假设可能存在重复的参数名称。如果有重复的名字,那么字典会抛出异常。

于 2012-01-13T16:53:27.927 回答
5

为什么要使用正则表达式来拆分它?

您可以先提取查询字符串。在 & 上拆分结果,然后通过从 = 上拆分结果来创建地图

于 2008-11-23T22:13:39.113 回答
1

您没有指定您正在使用哪种语言,但这应该可以在 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();
        }
    }
}
于 2008-11-24T00:00:23.063 回答
0

使用正则表达式首先找到键值对然后进行拆分......似乎不对。

我对完整的正则表达式解决方案感兴趣。

任何人?

于 2008-11-23T23:14:20.910 回答
0

看一下这个

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

您可以通过 Groups["key"].Captures[i] & Groups["value"].Captures[i] 获得对

于 2008-11-23T23:17:33.383 回答
0

也许是这样的(我对正则表达式很生疏,而且一开始并不擅长它们。未经测试):

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

(顺便说一下,XHTML 格式不正确;& 应该是 & 在属性中。)

于 2008-11-23T23:23:49.143 回答
0

一个克服排序问题的简单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')]
于 2008-11-24T14:18:03.253 回答
0

另一种方法是将捕获组放在前瞻中:

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

如果只有两个参数,则没有理由比 Mike 和 strager 建议的基于交替的方法更喜欢这种方式。但是,如果您需要匹配三个参数,其他正则表达式将增长到其当前长度的几倍,而这个正则表达式只需要另一个前瞻,就像现有的两个一样。

顺便说一句,与您对克劳斯的回应相反,您使用哪种语言非常重要。从一种语言到另一种语言,功能、语法和 API 存在巨大差异。

于 2008-11-24T05:34:16.057 回答
0

您没有说您使用的是哪种正则表达式风格。由于您的示例 URL 链接到 .aspx 文件,我将假设为 .NET。在 .NET 中,一个正则表达式可以有多个具有相同名称的命名捕获组,并且 .NET 会将它们视为一个组。因此,您可以使用正则表达式

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

这个带有交替的简单正则表达式将比任何环视技巧更有效。如果您的要求包括仅在参数位于链接中时匹配参数,则可以轻松扩展它。

于 2008-11-24T09:36:19.297 回答