Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > VB6 > Проблемы с парсингом текстовой строки


Автор: mihanik 12.1.2007, 15:27
Привет всем!!!
С Новым годом.

У мня проблемы с парсингом.
Имею стоку, в которой находися текст, похожий на содержимое ini-файла, а именно

Цитата

[start]
top=1
[stop]
left = 5
bottom=2


Хочу написать процедурку, которая определяла, есть ли секция ini-файла с нужным мне именем или нет и есть ли в этой секции ключ с нужным мне именем...

Для экспериментов создал маленькую процедурку...

Код

Private Sub Command4_Click()

Dim myRegExp As New RegExp          ' создаём экземпляр RegExp'a
Dim aMatch As Match                 ' один из совпавших образцов
Dim colMatches As MatchCollection   ' коллекция этих образцов

Dim S As String
Dim P As String
Dim section As String
Dim iniKey As String

    S = "[start]" & vbCrLf & _
        "top=1" & vbCrLf & _
        "[stop]" & vbCrLf & _
        "left = 5   " & vbCrLf & _
        "bottom=2"
    
    section = "start"
    iniKey = "top"
    
    P = "[.|\n]*\n*\s*\[\s*" & section & "\s*\]\s*\n*[.|\n]*\n*\s*" & iniKey & "\s*=\s*\w*\s*\n*[.|\n]*"
    
    ' Устанавливаем параметры myRegExp
    myRegExp.Global = True
    myRegExp.IgnoreCase = True
    myRegExp.MultiLine = True
    myRegExp.Pattern = P
    
    Set colMatches = myRegExp.Execute(S)
    
    For Each aMatch In colMatches ' проходим по всей коллекции
        MsgBox aMatch.FirstIndex & "," & aMatch.Length & "," & aMatch.Value
    Next aMatch
    
End Sub


Проблема заключается в том, что если устанавливаю

Код

    section = "start"
    iniKey = "top"


или

Код

    section = "stop"
    iniKey = "left "


То всё находится, а если 

Код

    section = "stop"
    iniKey = "bottom"


То ничего не находится.

Ля-ля-ля, жу-жу-жу,
Я сегодня торможу...



Автор: Naghual 12.1.2007, 15:33
По моему проще использовать стандартные методы для работы с ИНИ файлами.

Автор: mihanik 12.1.2007, 15:35
Это API-функции?
Пробовал.
Работает.
Хочу сам.

Мы (комсомольцы) хотим секса.
Но в гамаке и стоя!!!  smile

Добавлено @ 15:39 
Мне бы только Pattern  кто-нибудь помог бы подправить...

Автор: Black_Star 12.1.2007, 16:43
mihanik, http://www.rsdn.ru/article/alg/regular.xml

Автор: W4FhLF 12.1.2007, 17:44
(\[start\]\x0D\x0A)( *\w+ *\= *\d{1,6} *\x0D\x0A)*(top *\= *\d{1,6} *\x0D\x0A)

Добавлено @ 17:50 
На твоём примере проверял:
[start]
top=1
[stop]
left = 5
bottom=2


Автор: mihanik 13.1.2007, 10:48
W4FhLF, 

Тогда уж переработав для моего примера получим

Код

P = "(\[" & section & "\]\x0D\x0A)( *\w+ *\= *\d{1,6} *\x0D\x0A)*(" & iniKey & "*\= *\d{1,6} *\x0D\x0A)"


Не работает...  smile 

Black_Star,  спасибо за ссылочку.
В MSDN всё примерно то же...
Но, всё равно спасибо.  smile 

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

Думаю....

Автор: mihanik 13.1.2007, 11:10
По-моему, у меня проблемы с прожорливостью регулярного выражения...

Автор: W4FhLF 13.1.2007, 11:16
Цитата(mihanik @  13.1.2007,  10:48 Найти цитируемый пост)
У меня-то проблема в основном с тем, что если искомый ключ стоит сразу после названия секции, то он находится, а если между названием секции и самим ключём стоит ещё один или несколько ключей, то ничего не выдаётся... 


Ну как не работает? Ты же видишь я учёл этот момент: ( *\w+ *\= *\d{1,6} *\x0D\x0A)*
Это говорит препроцессору о том, что между твоей секцией и ключом могут находиться ещё несколько ключей. 

Беру вот такой пример:

Код

S = "[start]" & vbCrLf & _
        "top=1" & vbCrLf & _
        "[stop]" & vbCrLf & _
        "left = 5   " & vbCrLf & _
        "bottom=2"
    
    section = "start"
    iniKey = "top"
    
    myRegExp.Pattern = "(\[" & section & "\]\x0D\x0A)( *\w+ *\= *\d{1,6} *\x0D\x0A)*(" & iniKey & "*\= *\d{1,6} *\x0D\x0A)"
    
    Set colMatches = myRegExp.Execute(S)
    For Each aMatch In colMatches
        MsgBox aMatch.Value
    Next aMatch


Как результат на экране одно сообщение:

Цитата

---------------------------
Project1
---------------------------
[start]
top=1
---------------------------
ОК   
---------------------------


Теперь усложняю текст:

Код

    S = "[start]" & vbCrLf & _
        "somekey=1" & vbCrLf & _
        "top=1" & vbCrLf & _
        "[stop]" & vbCrLf & _
        "left = 5   " & vbCrLf & _
        "bottom=2"


Всё остальное оставляю так же. Как результат на экране вот такое сообщение:
Цитата

---------------------------
Project1
---------------------------
[start]
somekey=1
top=1
---------------------------
ОК   
---------------------------


Так, что это выражение учитывает все условия, который ввёл изначально. 

Автор: mihanik 16.1.2007, 09:14
W4FhLF, спасибо за участие!!!  smile 

Вечером проверю твой вариант...
Посмотрю, что лучше работает.
Как только проверю, - отмечусь на форуме.

У меня тоже получилось написать регулярное выражение.
Вчера тестил... Вроде ничего...
Работает...
Я, правда, усложнил чуть-чуть условие.
Значение ключа стал брать в кавычки. т.е. примерно так...

Цитата

[start]
somekey="1"
top="1"


Ну... Это уже мои заморочки... smile

Автор: mihanik 16.1.2007, 21:44
W4FhLF!!!

Не обижайся, но твой паттерн не работает...

Работает такой

Код

myRegExp.Pattern  = "^\s*\[\s*" & Section & "\s*\]\s*$[^.$]*^\s*" & iniKey & "\s*=\s*"".*""\s*$"


Он требует небольшой доработки, но в принципе пока меня устраивает...
Вот, какая функция у меня получилась...

Код

' Метод "получить значение ключа"
Public Function GetKeyValue(ByVal iniSection As String, ByVal iniKey As String, Optional ByVal iniDefaultValue As String) As String
Dim myRegExp As New RegExp          ' создаём экземпляр RegExp'a
Dim aMatch As Match                 ' один из совпавших образцов
Dim colMatches As MatchCollection   ' коллекция этих образцов
Dim iniP As String
Dim S As String
Dim P1, P2 As Long
    
    Err = 0
    If IsMissing(iniDefaultValue) Then iniDefaultValue = ""
    
    iniP = "^\s*\[\s*" & iniSection & "\s*\]\s*$[^.$]*^\s*" & iniKey & "\s*=\s*"".*""\s*$"
    
    ' Устанавливаем параметры myRegExp
    myRegExp.Global = True
    myRegExp.IgnoreCase = True
    myRegExp.MultiLine = True
    myRegExp.Pattern = iniP

    Set colMatches = myRegExp.Execute(iniText)
    
    Select Case colMatches.Count
        Case 0:
                    GetKeyValue = iniDefaultValue
                    Err = 4
                    Exit Function
        Case 1:
                    S = colMatches.Item(0).Value
        Case Else:
                    S = colMatches.Item(0).Value
                    Err = 3
    End Select

    P2 = InStrRev(S, """")
    P1 = InStrRev(S, """", P2 - 1)
    S = Mid(S, P1 + 1, P2 - P1 - 1)
    
    GetKeyValue = S
    
End Function

Автор: W4FhLF 17.1.2007, 12:52
Цитата(mihanik @  16.1.2007,  21:44 Найти цитируемый пост)
Не обижайся, но твой паттерн не работает...


Да я не обижаюсьsmile Просто дело в том, что ты изначально не описал как следует шаблон, поэтому составить рабочее выражение, удовлетворяющее в полной мере твоим ребованиям, не удалось. А те требования, которые ты выдвинул вначале я учёл в своём выражении, твоё же финальное выражение описывает совсем иной шаблон, нежели начальные. Ну да ладно, разобрался сам, тем лучше.

Автор: mihanik 17.1.2007, 13:09
W4FhLF, всё равно спасибо!!! 

 smile 

За "соучастие" получай в репу!!!

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)