2008-11-23 9 views
1

J'ai un HTML avec le contenu suivant:Regex pour analyser les valeurs querystring aux groupes nommés

... 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 ... 

Je voudrais analyser cela et obtenir un match avec des groupes nommés:

Match 1:

groupe [ "utilisateur"] = 123

groupe

[ "article"] = 2

Match 2

groupe

[ "utilisateur"] = 678

groupe

[ "section"] = 5

je peux le faire si les paramètres vont toujours dans l'ordre, d'abord l'utilisateur et la section , mais je ne sais pas comment le faire si l'ordre est différent.

Merci! Pourquoi utiliser regex pour le découper?

+0

Est-ce que 'user' est identique à 'userId'? –

Répondre

5

Pourquoi utiliser regex?

Vous pouvez d'abord extraire la chaîne de requête. Diviser le résultat sur & et ensuite créer une carte en divisant le résultat de celui sur =

+0

query.Split ('&'). ToDictionary ((s) => s.Substring (0, s.IndexOf ('=')), (s) => s.Substring (s.IndexOf ('=') + 1)); –

0

Utiliser regex pour trouver d'abord les paires de valeurs de clé, puis faire des séparations ... ne semble pas correct.

Je suis intéressé par une solution regex complète.

Quelqu'un?

0

Check this out

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

Vous pouvez obtenir des paires avec quelque chose comme groupes [ "touche"]. Capture [i] & Groupes [ "valeur"]. Capture [i]

0

Peut-être quelque chose comme ça (je suis rouillé sur regex, et n'a pas été bon à eux en premier lieu de toute façon non testé.):

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

(soit dit en passant, le XHTML est malformé, & devrait être & amp; dans les attributs)

1

Vous n'avez pas spécifié quelle langue vous travaillez, mais cela devrait faire l'affaire en 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

Une autre approche consiste à mettre les groupes de capture à l'intérieur lookaheads:

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

S'il n'y a que deux paramètres, il n'y a aucune raison de préférer ainsi les approches basées sur l'alternance suggérées par Mike et strager. Mais si vous deviez faire correspondre trois paramètres, les autres expressions régulières augmenteraient jusqu'à plusieurs fois leur longueur actuelle, alors que celle-ci n'aurait besoin que d'un autre lookahead comme les deux existantes.À propos, contrairement à votre réponse à Claus, la langue dans laquelle vous travaillez est très importante. Les capacités, la syntaxe et l'API varient énormément d'une langue à l'autre.

0

Vous n'avez pas dit quelle saveur regex vous utilisez. Étant donné que l'URL de votre exemple est liée à un fichier .aspx, je suppose que .NET. Dans .NET, une seule expression régulière peut avoir plusieurs groupes de capture nommés avec le même nom, et .NET les traitera comme s'il s'agissait d'un groupe. Ainsi, vous pouvez utiliser la regex

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

Cette regex simple alternance sera beaucoup plus efficace que tous les tours avec lookaround. Vous pouvez facilement l'étendre si vos besoins incluent la correspondance des paramètres uniquement s'ils sont dans un lien.

0

une implémentation simple python surmonter le problème de commande

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')] 
7

Dans mon cas, je devais analyser une URL car l'utilitaire HttpUtility.ParseQueryString n'est pas disponible dans WP7. Donc, j'ai créé une méthode d'extension comme ceci:

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); 
     } 
    } 
} 

Ensuite, il est question d'utiliser, par exemple

 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"]; 

REMARQUE: Je retourne le IEnumerable au lieu du dictionnaire directement juste parce que Je suppose qu'il pourrait y avoir le nom du paramètre dupliqué. S'il y a des noms en double, le dictionnaire lèvera une exception.

+0

Bonne regex pour l'analyse querystring: '[\? &] (? [^ & =] +) = (? [^ & =] +)' ou avec une légère modification, juste pour querystrings: '[^ &] (? [^ =] +) = (? [^ & =] *) ' – GlennG

Questions connexes