Eng | Rus
 
Обучение -> Статьи -> Использование регулярных выражений
 
 
 
Simple Seo Solutions
SEO и Продвижение
сайтов
Speechpad.ru
Голосовой набор текстаГолосовой набор текста

Использование регулярных выражений на примере VB.NET.

Основные принципы

1. Регулярные выражения ищут текст, совпадающий с определенным шаблоном.

2. Регулярные выражения работают на уровне совпадений отдельных символов.

Для пояснения этих принципов рассмотрим следующий пример:

Необходимо выделить из строки некоторого оператора SQL SELECT  FROM название полей и их описание.
Проанализировав синтаксис оператора Select, приходим к выводу, что нужно выделить часть строки, идущую перед FROM, а затем постараться выделить названия полей и их описание.
Допустим,что в этом операторе используется для описания полей(если они есть) ключевое слово AS. Кроме того могут использоваться квадратные скобки для обрамления описания и стандарные функции для получения полей оператора SELECT.
Например SELECT ROUND(first,3) as [quantity of word, million], ROUND(second,3)as[quantity of errors, billion]FROM(mytable).
Таким образом, задача усложняется наличаем квадратных и круглых скобок, которые могут в свою очередь, содержать запятые. Нужно выражение, выделяющее запятые, не входящие в незакрытую круглую или квадратную скобку.
В документации о регулярных выражениях в .NET описывается группа (?! ) с непереводимым названием "Zero-width positive lookahead assertion". Которая вроде может указывать на группу, которая не должна предшествовать искомому выражению.
После небольших но тяжелых мучений с негативной логикой, пытаемся перейти в позитивную и искать, наоборот запятые, которые входят в такие скобки и их потом не учитывать.
Наверное, это может в конечном счете привести к цели, но на мой взгляд цель в данном случае не оправдывает средств. В конечном счете приходим к следующему компромиссу между программной логикой и использованием регулярных выражений (Строка, передаваемая в данном примере в функцию не содержит ведущего ключевого слова SELECT - по условиям задачи его не было):

 

	
	
    Function ParseStrSelect(ByVal str As String) As IList
        Dim errors As String
        errors = "ok"

        Dim strbeg As String
        Dim strend As String
        Dim pos As Integer
        Dim fields As New System.Collections.ArrayList

        Dim pat As String = "[\s\[\)](from)[\s\(\[]"
        ' Compile the regular expression.
        Dim r As Regex = New Regex(pat, RegexOptions.IgnoreCase)
        Dim match As Match
        match = r.Match(str)



        Dim mystr As String() '= r.Split(str)
        strbeg = str.Substring(0, match.Index + 1)
        strend = str.Substring(match.Index + match.Length - 1)

        Dim azp As Integer, akr As Integer, akv As Integer
        pos = 0
        Do
            azp = strbeg.IndexOf(",", pos)
            akr = strbeg.IndexOf("(", pos)
            akv = strbeg.IndexOf("[", pos)
            Select Case firsrtchar(azp, akr, akv)
                Case -1
                    fields.Add(strbeg.Substring(0))

                    Exit Do
                Case 1
                    fields.Add(strbeg.Substring(0, azp))

                    strbeg = strbeg.Substring(azp + 1)
                    pos = 0
                Case 2 ' "(" found
		    pos = akr
                    pos = strbeg.IndexOf(")",pos)
                    If pos = -1 Then
                        errors = "( don't match"
                        Exit Do
                    End If

                Case 3
		    pos = akv
                    pos = strbeg.IndexOf("]",pos)
                    If pos = -1 Then
                        errors = "[ don't match"
                        Exit Do
                    End If



            End Select
        Loop

        If errors = "ok" Then
            Return fields
        Else
            Return Nothing
        End If
    End Function
    'return 1 - , 2 - ) 3 - [ -1 - not found ,
    Function firsrtchar(ByVal zp As Integer, ByVal kr As Integer, ByVal kv As Integer)
        If zp = -1 Then Return -1
        If kr = -1 Then kr = 10000
        If kv = -1 Then kv = 10000
        If zp < kr And zp < kv Then Return 1
        If kr < zp And kr < kv Then Return 2
        If kv < zp And kv < kr Then Return 3
    End Function
			
			
Программу можно использовать следующим образом:

ParseStrSelect("ROUND(first,3) as [quantity of word, million], ROUND(second,3)as[quantity of errors, billion]FROM(mytable)" )

Часть программы, заполняющая список lstFields  полями и из описаниями из строк полученного массива fields приведена ниже:

			
	Function mytrim(ByVal str As String) As String
        Dim mystr As String
        mystr = str.Trim()
        If mystr.StartsWith("[") Then
            mystr = mystr.TrimStart("[")
            mystr = mystr.TrimEnd("]")

        End If
        Return mystr
    End Function
    Sub ParseField(ByVal str As String)
        Dim field As String
        Dim descr As String
        Dim pat As String = "[\s\[\)](as)[\s\(\[]"
        Dim r As Regex = New Regex(pat, RegexOptions.IgnoreCase)
        Dim match As Match
        match = r.Match(str)


        Dim fielditem As New ListItem
        If match.Success Then
            field = str.Substring(0, match.Index + 1)
            descr = str.Substring(match.Index + match.Length - 1)


        Else
            field = str
            descr = str
        End If
        fielditem.Value = field
        fielditem.Text = mytrim(descr)
        lstFields.Items.Add(fielditem)
    End Sub
			
			
			

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

Алексей Шечков, 2005.

© prjsoft.ru