2012-06-29 6 views
5

que tiene la siguiente cadena que deseo extraer partes de:hermoso bikini Manipulación

<FONT COLOR="GREEN">201 KAR 2:340.</FONT> 

En este caso particular, deseo para extraer los números de 201,2 y 340, que voy a utilizar más tarde para concatenar para formar otra cadena:

http://www.lrc.state.ky.us/kar/201/002/340reg.htm

tengo una solución, pero no es fácil de leer, y parece más bien torpe. Implica el uso de la función intermedia. Aquí está:

intTitle = CInt(Mid(strFontTag, 
        InStr(strFontTag, ">") + 1, 
        (InStr(strFontTag, "KAR") - InStr(strFontTag, ">")) 
          - 3)) 

Me gustaría saber si tal vez hay una mejor manera de abordar esta tarea. Me doy cuenta de que podría hacer algunos nombres descriptivos de variables, como intPosOfEndOfOpeningFontTag para describir lo que hace la primera función InStr, pero todavía me parece torpe.

¿Debería utilizar algún tipo de función dividida, regex o alguna forma más elegante que no haya encontrado todavía? He estado manipulando cadenas de esta manera durante años, y siento que debe haber una mejor manera. Gracias.

+0

Tengo que apreciar a alguien que activly se preocupa por la legibilidad ... desafortunadamente, no lo sé vb. – gbtimmon

+5

Disculpe, ¿esto es VB.net, VBA o VB6? – JimmyPena

+0

Se parece más a * VBScript * con todas las funciones de Variant utilizadas en él. – Bob77

Respuesta

1

patrón de expresión: <FONT[^>]*>.*?(\d+).*?(\d+).*?(\d+).*?<\/FONT>

1
<FONT[^>]*>[^\d]*(\d+)[^\d]*(\d+):(\d+)[^\d]*</FONT> 
+0

¡Algunas personas no saben qué son las expresiones regulares! –

1

La clase

Imports System 
Imports System.IO 
Imports System.Text 
Imports System.Text.RegularExpressions 
Imports System.Xml 
Imports System.Xml.Linq 
Imports System.Linq 

Public Class clsTester 
    'methods 
    Public Sub New() 
    End Sub 

    Public Function GetTitleUsingRegEx(ByVal fpath$) As XElement 
     'use this function if your input string is not a well-formed 
     Dim result As New XElement(<result/>) 
     Try 
      Dim q = Regex.Matches(File.ReadAllText(fpath), Me.titPattern1, RegexOptions.None) 
      For Each mt As Match In q 
       Dim t As New XElement(<title/>) 
       t.Add(New XAttribute("name", mt.Groups("name").Value)) 
       t.Add(New XAttribute("num1", mt.Groups("id_1").Value)) 
       t.Add(New XAttribute("num2", mt.Groups("id_2").Value)) 
       t.Add(New XAttribute("num3", mt.Groups("id_3").Value)) 
       t.Add(mt.Value) 
       result.Add(t) 
      Next mt 
      Return result 
     Catch ex As Exception 
      result.Add(<error><%= ex.ToString %></error>) 
      Return result 
     End Try 
    End Function 

    Public Function GetTitleUsingXDocument(ByVal fpath$) As XElement 
     'use this function if your input string is well-formed 
     Dim result As New XElement(<result/>) 
     Try 
      Dim q = XElement.Load(fpath).Descendants().Where(Function(c) Regex.IsMatch(c.Name.LocalName, "(?is)^font$")).Where(Function(c) Regex.IsMatch(c.Value, Me.titPattern2, RegexOptions.None)) 
      For Each nd As XElement In q 
       Dim s = Regex.Match(nd.Value, Me.titPattern2, RegexOptions.None) 
       Dim t As New XElement(<title/>) 
       t.Add(New XAttribute("name", s.Groups("name").Value)) 
       t.Add(New XAttribute("num1", s.Groups("id_1").Value)) 
       t.Add(New XAttribute("num2", s.Groups("id_2").Value)) 
       t.Add(New XAttribute("num3", s.Groups("id_3").Value)) 
       t.Add(nd.Value) 
       result.Add(t) 

      Next nd 
      Return result 
     Catch ex As Exception 
      result.Add(<error><%= ex.ToString %></error>) 
      Return result 
     End Try 
    End Function 

    'fields 
    Private titPattern1$ = "(?is)(?<=<font[^<>]*>)(?<id_1>\d+)\s+(?<name>[a-z]+)\s+(?<id_2>\d+):(?<id_3>\d+)(?=\.?</font>)" 
    Private titPattern2$ = "(?is)^(?<id_1>\d+)\s+(?<name>[a-z]+)\s+(?<id_2>\d+):(?<id_3>\d+)\.?$" 
End Class 

El uso

Sub Main() 
     Dim y = New clsTester().GetTitleUsingRegEx("C:\test.htm") 
     If y.<error>.Count = 0 Then 
      Console.WriteLine(String.Format("Result from GetTitleUsingRegEx:{0}{1}", vbCrLf, y.ToString)) 
     Else 
      Console.WriteLine(y...<error>.First().Value) 
     End If 

     Console.WriteLine("") 
     Dim z = New clsTester().GetTitleUsingXDocument("C:\test.htm") 

     If z.<error>.Count = 0 Then 
      Console.WriteLine(String.Format("Result from GetTitleUsingXDocument:{0}{1}", vbCrLf, z.ToString)) 
     Else 
      Console.WriteLine(z...<error>.First().Value) 
     End If 
     Console.ReadLine() 
    End Sub 

Espero que esto ayude.

+0

¿Puedes explicar o al menos comentar tu código? Parece hacer mucho más de lo que realmente se pidió sin obvio "el resultado es XYZ". – Deanna

+0

@ Deanna: ¿has conseguido el código?Al publicar una respuesta en un período corto de tiempo, no siempre es posible comentar cada parte del código con detalles. También requiere que el solicitante tenga conocimiento de eso. – Cylian

+0

No es motivo para no explicar 2 páginas de código de caja negra sin commentar (y aparentemente excesivo) para una simple extracción de cadena. Has tenido 4 meses desde entonces para comentarlo :) – Deanna

0

creo @ Jean-François Corbett tiene razón.

esconderlo en una función y nunca mirar hacia atrás

cambiar el código para esto:

intTitle = GetCodesFromColorTag("<FONT COLOR="GREEN">201 KAR 2:340.</FONT>") 

Crear una nueva función:

Public Function GetCodesFromColorTag(FontTag as String) as Integer 

    Return CInt(Mid(FontTag, InStr(FontTag, ">") + 1, 
       (InStr(FontTag, "KAR") - InStr(FontTag, ">")) 
       - 3)) 

End Function