2010-09-16 4 views
0

J'ai une chaîne et ont besoin d'un motif de RegEx pour cela, donc je peux extraire uniquement la date et les numéros des tags:motif RegEx dans .VB

Dim a as string= "<table id=table-1 > <tbody> <td align=right> <h2 id=date-one>12.09.2010</h2> </td> </tr> </tbody></table> <table id=table-2 border=0 cellspacing=0 cellpadding=0><tbody><tr><td align=center valign=middle><h3 id=nb-a>01</h3></td><td align=center valign=middle><h3 id=nb-a>>02</h3></td><td align=center valign=middle><h3 id=nb-a>03</h3></td></tr></tbody></table>" 

Cette chaîne aura plus d'un bloc de des données similaires ... donc je dois être en boucle ... Merci! Adrian

+2

Utiliser un analyseur HTML (par exemple, http://htmlagilitypack.codeplex.com/), non Regex. – jball

+0

lecture obligatoire - http://stackoverflow.com/questions/tagged/regex%2bhtml?sort = votes & pagesize = 30 – jball

+0

Aussi, pour l'analyseur, voir http://stackoverflow.com/questions/846994/how-to-use-html-agility-pack – jball

Répondre

1

Un analyseur HTML (par exemple, le HtmlAgilityPack) sera plus simple à long terme, mais comme un guide pour Regex voici comment faire pour votre cas:

Dim pattern As String = "" 'what goes here? 
    ' wrapping line for viewing, 
    ' imagine the following is a single line 
    Dim a As String = 
    "<table id=table-1 > <tbody> <td align=right> 
    <h2 id=date-one>12.09.2010</h2> </td> </tr> </tbody></table> 
    <table id=table-2 border=0 cellspacing=0 cellpadding=0> 
    <tbody><tr><td align=center valign=middle><h3 id=nb-a>01 
    </h3></td><td align=center valign=middle><h3 id=nb-a>>02 
    </h3></td><td align=center valign=middle><h3 id=nb-a>03</h3> 
    </td></tr></tbody></table>" 
    ' end of the a variable declaration 
    For Each match As Match In Regex.Matches(a, pattern) 
    Console.WriteLine("Found '{0}' at position {1}", match.Value, match.Index) 
    Next 

Naïvement pour le premier match de tentative les numéros:

Dim pattern As String = "[\d]+" ' \d matches any number, 
            ' + specifies one or more 

Bien sûr, les matches trop nombreux articles et ne correspond pas à la date comme un seul groupe. Dans votre cas, chaque match est dans une balise et est donc précédé d'un '>' suivi d'un '<'.

Dim pattern As String = ">[.\d]+<" ' allow the '.' as well as numbers 
            ' capture any string that starts with '>' 
            ' followed by one or more numbers and '.' 
            ' ending with '<' 

Cela inclut Unforturnately le '>' et '<' dans vos matchs. Maintenant, nous avons besoin lookbehind positif et positif préanalyse:

Dim pattern As String = "(?<=>)[.\d]+(?=<)" 
            ' (?<=regex) is positive lookbehind for regex 
            ' (?=regex) is positive lookahead for regex 
            ' capture any string after '>' 
            ' with by one or more numbers and '.' 
            ' before '<' 

Maintenant, les choses se présentent bien parce que nous sommes correspondant à seulement la date et trois chiffres! Cependant, que se passerait-il si la date était séparée par '-' ou '/' au lieu de '.'?

Dim pattern As String = "(?<=>)[-/.\d]+(?=<)" 
            ' add '-' and '/' to date separators 

Facilement manipulé. Mais que se passe-t-il s'il y a des espaces avant ou après le numéro ou la date dans le texte de l'élément?

Dim pattern As String = "(?<=>\s*)[-/.\d]+(?=\s*<)" 
            ' lookbehind regex is ">\s*" means match 
            ' the char '>' 
            ' followed by 0 or more whitespace chars 
            ' lookahead regex is "\s*<" means match 
            ' 0 or more whitespace chars 
            ' followed by the char '<' 

Pas si mal. Le seul problème est que cette méthode demande encore plus d'effort et casse plus facilement que l'utilisation d'un analyseur html pour parcourir tous les éléments, vérifier si le texte de l'élément est un nombre ou une date valide et ajouter le texte des éléments correspondants à une liste. Considérons par exemple la modification de la méthode Regex pour gérer les devises (où "$ 100.03.45" ne devrait pas correspondre) ou la virgule en chiffres ou en s'assurant que les dates ont exactement trois groupes, chacun avec un, deux ou quatre chiffres, où seulement un groupe peut en avoir quatre, et l'un des groupes à deux chiffres ne peut pas dépasser 12, etc. La folie se trouve dans cette voie.

2

Juste en partant de l'exemple posté par jball. Je pensais simplement que ce serait plus facile que de se préoccuper d'une regex lookbehind ou d'une regex lookahead. Ici, j'ai utilisé des parenthèses pour tirer parti de Match.Groups.

m.Groups (0) .Value = "> XXXXXX <"

m.Groups (1) .Value = ">"

m.Groups (2) .Value = "xxxxxx"

m.Groups (3) .Value = "<"

Dim input As String = "<table id=table-1 > <tbody> <td align=right> <h2 id=date-one>12.09.2010</h2> </td> </tr> </tbody></table> <table id=table-2 border=0 cellspacing=0 cellpadding=0><tbody><tr><td align=center valign=middle><h3 id=nb-a>01</h3></td><td align=center valign=middle><h3 id=nb-a>>02</h3></td><td align=center valign=middle><h3 id=nb-a>03</h3></td></tr></tbody></table>" 

     Dim regex1 As Regex = New Regex("(>)([\d.]+)(<)") 
     Dim matches As MatchCollection = regex1.Matches(input) 

     For Each m As Match In matches 
      Console.WriteLine(String.Format("{1}{0}", m.Groups(2).Value, Environment.NewLine)) 
     Next 
Questions connexes