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


Автор: error0x40 17.6.2013, 17:47
Примеры строк:
1. Type ( "Name 1" )
2. Engine( Name )
3. Class ( Name Folder )
4. Wagon ( "Name" "Folder")
5. Discrete_Trigger ( 53    PlayOneShot ( 2 File ( "Name" -1 ) File ( "Name2" -1 ) SelectionMethod ( RandomSelection ) ) )

На выходе нужно получить следующее
1. "Name 1"
2. Name
3. Name Folder
4. "Name"  "Folder"
5. "Name" "Name2"

Все корректно работает кроме 5 позиции:
"Name" -1 "Name2" -1 SelectionMethod ( RandomSelection

Приведу код самой функции

Код

   Function GetStore(ByVal Text As String, ByVal Argument As String)
        Dim pattern As String = "Argument\s\(\s.*\s\)|Argument\(\s.*\s\)"
        Dim PatRepl As String = "Argument\s\(\s|Argument\(\s|\s\)"
        Dim Temp As String = Nothing

        'Замена слова Argument на реальный аргумент
        pattern = pattern.Replace("Argumnet", Argument)
        PatRepl = PatRepl.Replace("Argument", Argument)
        'Выделение аргумента со значением
        Temp = Regex.Match(Text, pattern).Value
        'Выделить только значение
        Temp = Regex.Replace(Temp, PatRepl, "")
        Return Temp
    End Function


Подскажите пожалуйста, что именно упустил из виду?

П.С. Приветствуются любые альтернативные варианты на PB.

Автор: Akina 18.6.2013, 08:11
Цитата(error0x40 @  17.6.2013,  18:47 Найти цитируемый пост)
что именно упустил из виду?

1) Вложенные скобки (вернее, они должны соответствовать друг другу в паттерне)
2) Набор символов, который не может быть в составе подстроки (возможно, в определённой позиции, напр. не начинаться xc цифры или дефиса)
3) Специальные подстроки, требующие исключения

Как я понимаю, в 5-м примере должно получиться "Name" "Name2" RandomSelection?

Автор: diadiavova 18.6.2013, 11:05
Цитата(error0x40 @  17.6.2013,  18:47 Найти цитируемый пост)
П.С. Приветствуются любые альтернативные варианты на PB.

Достаточно сложно советовать, в силу того, что ты не объяснил саму задачу. Из примеров, конечно же, можно кое-что понять, но полной ясности все-таки нет. Мне вообще вариант с заменой части паттерна кажется немного странным, особенно если учесть, что само выражение у тебя предельно простое, я предполагаю, что можно все вместить в один паттерн и ничего не заменять.
Например, если т.н. аргумент состоит из известных символов, то можно его просто описать регуляркой. В случае, если он может состоять из любых символов, то регулярка вообще может накрыться. Поэтому надо бы ввести какое-то ограничение. Например, во всех твоих примерах то, что ты назвал аргументом состоит из алфавитно-цифровых символов и подчеркиваний. Ну это ведь можно описать простейшей регуляркой \w+. Если тебе надо выбрать содержимое скобок, то тут тоже все предельно просто и такая регулярка будет выглядеть так [^\(\)]+. Ну и далее аналогично, то есть надо точно сформулировать правила отбора, а потом уже сочинять регулярку.

Автор: error0x40 18.6.2013, 15:13
Akina
на выходе следовало получиться:
"Name" "Name2"

diadiavova
Цитата

то есть надо точно сформулировать правила отбора, а потом уже сочинять регулярку. 

Как синтаксически грамотно описать РВ - вот в чем загвоздка.

Ладно на время забудем, что аргументы могут быть разными.

Критерии выбора подстроки:
1.Начало подстроки - слово(Argument) + пробел со скобкой/скобка (Например: 'Argument (' либо 'Argument('  )
2. "В середине подстроки" могут присутствовать символы алфавита, цифры и символы: / \ . _ -  " (пробел)  
2.Конец подстроки - пробел с закрывающей скобкой

Вот код рабочии, но необходимо оптимизировать
Код

    Function GetStore(ByVal Text As String, ByVal Argument As String)
        Dim pattern As String = Argument & "\ \(\ .*?\ \)|" & Argument & "\(\ .*?\ \)"
        Dim PatRepl As String = Argument & "\ \(\ |" & Argument & "\(\ |\ \)| -1"
        Dim Temp As String = Nothing
        Dim Temp2 As String = Nothing
        'Выделение аргумента со значением
        Temp = Regex.Match(Text, pattern, RegexOptions.IgnoreCase).ToString
        Temp2 = Regex.Match(Text, pattern, RegexOptions.IgnoreCase).NextMatch.ToString
        If Temp2 <> Nothing Then Temp &= "|" & Temp2
        'Выделить только значение
        Temp = Regex.Replace(Temp, PatRepl, "", RegexOptions.IgnoreCase)
        Return Temp
    End Function


Не понятно следующее как сделать, что бы поиск соответствовал выше описанным критерия, но при это критерии начала и конца игнорировались оставалось лишь значение?
Т.е. как описать  в одном РВ так, что бы из строки например "Argument ( "\Value_.0" )  получить только "\Value_.0"
Есть еще такая вот трактовка: Как объединить действия  7  и 11 строки в одну.

Автор: diadiavova 18.6.2013, 15:56
Цитата(error0x40 @  18.6.2013,  16:13 Найти цитируемый пост)
Начало подстроки - слово(Argument)

Означает ли это, что оно состоит только из алфавитно-цифровых символов? Если да, то вполне подойдет \w+ .
Цитата(error0x40 @  18.6.2013,  16:13 Найти цитируемый пост)
1.Начало подстроки - слово(Argument) + пробел со скобкой/скобка (Например: 'Argument (' либо 'Argument('  )
2. "В середине подстроки" могут присутствовать символы алфавита, цифры и символы: / \ . _ -  " (пробел)  
2.Конец подстроки - пробел с закрывающей скобкой

Допустим. Тогда не очень понятно, каким образом из пятого варианта получится представленный тобой результат. В частности меня интересует, куда делись подстроки "-1" (дважды) и "RandomSelection". Кроме того, интересно, следует ли объединять все полученные результаты в одну строку, как это у тебя описано в варианте 5. Ведь  "Name" и "Name2" находятся не рядом.
Так вообще по описанному получается примерно следующее
Код

\w+\s?([\w\/\\\.\-]+\s\)
Естественно, для извлечения именно содержимого скобок надо его заключить в именованную группу и именно ее и искать в результатах
Код

\w+\s?\((?<result>[\w\/\\\.\-]+)\s\)
То, что я написал - не готовая регулярка, а просто набросок, который скорей всего еще надо будет отладить. Символы \s обозначают не только проблелы, но и табуляции и новую строку( Chr(10) ) и возврат каретки (Chr(13)). Ну и соответственно вопросы, которые задал выше, тоже надо учесть.

Автор: Akina 18.6.2013, 16:45
Цитата(error0x40 @  18.6.2013,  16:13 Найти цитируемый пост)
Akina
на выходе следовало получиться:
"Name" "Name2"

Не понимаю, чем они лучше RandomSelection

Автор: error0x40 18.6.2013, 17:59
Цитата(diadiavova @  18.6.2013,  15:56 Найти цитируемый пост)
Означает ли это, что оно состоит только из алфавитно-цифровых символов? Если да, то вполне подойдет \w+ .

Используется конкретное слово(Argument), т.е. \w в данном случае не подойдет.

Цитата(diadiavova @  18.6.2013,  15:56 Найти цитируемый пост)
Допустим. Тогда не очень понятно, каким образом из пятого варианта получится представленный тобой результат. В частности меня интересует, куда делись подстроки "-1" (дважды) и "RandomSelection". Кроме того, интересно, следует ли объединять все полученные результаты в одну строку, как это у тебя описано в варианте 5. Ведь  "Name" и "Name2" находятся не рядом.

Если обратить внимание на вот это строчку, том можно увидеть где выражение " -1" удаляется из результата:

Код

Dim PatRepl As String = Argument & "\ \(\ |" & Argument & "\(\ |\ \)| -1"

А насчет 5-го результата то вот строки отвечающие за вывод 2-х значений

Код

        Temp2 = Regex.Match(Text, pattern, RegexOptions.IgnoreCase).NextMatch.ToString
        If Temp2 <> Nothing Then Temp &= "|" & Temp2


Цитата(diadiavova @  18.6.2013,  15:56 Найти цитируемый пост)
Естественно, для извлечения именно содержимого скобок надо его заключить в именованную группу и именно ее и искать в результатах

Во это, что мне нужно было, про группы я забыл т.к. давно не работал с PB. Спасибо

Цитата(diadiavova @  18.6.2013,  15:56 Найти цитируемый пост)
То, что я написал - не готовая регулярка, а просто набросок, который скорей всего еще надо будет отладить. Символы \s обозначают не только проблелы, но и табуляции и новую строку( Chr(10) ) и возврат каретки (Chr(13)). Ну и соответственно вопросы, которые задал выше, тоже надо учесть. 

Символ \s тоже не подходит так как в  подстроке встречается только пробел.

Кстати проверил мой старый код с использование стандарных функции и новый написаный с помощь РВ.
Вот результат:
                                     Простые функции                         С использование РВ
По времени(Tick)                                        одинаковое
Количество срок  кода               45                                                     23

Автор: diadiavova 18.6.2013, 23:54
Цитата(Akina @  18.6.2013,  17:45 Найти цитируемый пост)
Не понимаю, чем они лучше RandomSelection 

Насколько я понял, ему нужны не все вхождения текста в скобках, а только те, которым предшествует конкретный аргумент.
Цитата(error0x40 @  18.6.2013,  18:59 Найти цитируемый пост)
Используется конкретное слово(Argument), т.е. \w в данном случае не подойдет.

Ну почему не подойдет? А если так?
Код

    Function GetStore(text As String, arg As String) As String
        Dim pattern = "(?<argument>\w+)\x20?\(\x20?(?<result>[\""\w\/\\\.\-]+)(\x20-1)?\x20\)"
        Dim re As New Regex(pattern, RegexOptions.Compiled Or RegexOptions.IgnoreCase)
        Dim matches = From m As Match In re.Matches(text) Where m.Groups("argument").Value = arg Select m.Groups("result").Value
        Return String.Join(" ", matches.ToArray)
    End Function

Цитата(error0x40 @  18.6.2013,  18:59 Найти цитируемый пост)
Если обратить внимание на вот это строчку

Если обратить, то конечно, только когда задаешь вопрос наверно как-то неправильно вынуждать тех, кто готов помочь, угадывать что тебе надо по коду, который к тому же еще и работает не так как надо. Все-таки проблему надо сформулировать словами, а код обычно служит для пояснения.
Цитата(error0x40 @  18.6.2013,  18:59 Найти цитируемый пост)
Символ \s тоже не подходит так как в  подстроке встречается только пробел.

Ну его заменить пробелом тоже не проблема. Можно просто пробел ставить, но это не подойдет, если установить флажок IgnorePatternWhitespaces. В примере выше я использовал более универсальный подход.
Цитата(error0x40 @  18.6.2013,  18:59 Найти цитируемый пост)
Кстати проверил мой старый код с использование стандарных функции и новый написаный с помощь РВ.

Если ты не приводишь самих тестов и что тестировал, то эти результаты вообще ни о чем не говорят. Они просто непонятны.

Автор: error0x40 21.6.2013, 18:58
Всем спасибо.

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