Переключение на Главную Страницу Страницы: [1] 2  ОтправитьПечать
Горячая тема (более 10 ответов) VBScript.RegExp: обрамляющие конструкции (число прочтений - 11264 )
The gray Cardinal
Full Member
***
Отсутствует



Сообщений: 159
Зарегистрирован: 17. Июня 2006
Пол: Мужской
VBScript.RegExp: обрамляющие конструкции
20. Августа 2007 :: 19:52
Печать  
Вопрос по использованию регулярных выражений на VBScript: как правильно делать выражения нежадными? Например, нужно выделить из текста все конструкции, обрамлённые угловыми скобками (например, html-теги). Если написать:
Код
Выбрать все
<[\s\S]*> 


Будет всё неправильно, т.к. будет найден один большой фрагмент от первой открывающей скобки до последней закрывающей. Не нашёл ничего лучше, как написать:
Код
Выбрать все
<[^>]*> 


Это правильный подход или нет?
  
Наверх
www  
IP записан
 
artbear
1c++ developer
1c++ moderator
Отсутствует


Эх, дайте что-нибудь новенькое
да полезное потести

Сообщений: 6303
Местоположение: Москва
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: VBScript.RegExp: обрамляющие конструкции
Ответ #1 - 21. Августа 2007 :: 04:09
Печать  
ИМХО в данном случае правильный подход, иначе, как в первом случае, и будет "жадный" вариант.
ЗЫ а вообще-то вместо знака * точно есть "нежадный" эквивалент. В хелпе ВБСкрипта описан. Но на память не помню Печаль а доки временно под рукой нет Улыбка
Но и тебя и твой вариант должен устроить.
  

OpenConf developer :: http://openconf.1cpp.ru&&FormEx developer :: http://formex.dorex.ru&&1C++ active developer &amp;&amp; tester :: www.1cpp.ru
Наверх
GTalkSkype/VoIPICQ  
IP записан
 
kuntashov
Full Member
***
Отсутствует


1С:Специалист

Сообщений: 130
Местоположение: Саратов
Зарегистрирован: 13. Июня 2006
Пол: Мужской
Re: VBScript.RegExp: обрамляющие конструкции
Ответ #2 - 21. Августа 2007 :: 04:32
Печать  
"Жадность" вроде как "убирается" добавлением символа "?" к жадному оператору, разве в VB не так? У меня, вроде работает такой пример как надо:

Код
Выбрать все
Set re = New RegExp
re.IgnoreCase = true
re.Global = true
re.Pattern = "<[\s\S]*?>"
Set m = re.Execute("<t1><t2><t3>")
for each e in m
	WScript.Echo e & vbCrLf
next
 



результат:


<t1>

<t2>

<t3>
  

С уважением, &&Александр Кунташов&&http://kuntashov.ru/
Наверх
 
IP записан
 
The gray Cardinal
Full Member
***
Отсутствует



Сообщений: 159
Зарегистрирован: 17. Июня 2006
Пол: Мужской
Re: VBScript.RegExp: обрамляющие конструкции
Ответ #3 - 21. Августа 2007 :: 06:02
Печать  
a13x, спасибо, это оно! Улыбка

Есть ещё вопросец, чуть посложнее. Можно ли одним регулярным выражением найти все вхождения фразы, находящиеся вне определённых обрамляющих конструкций? Например, что-то вроде (искусственный пример):
Код
Выбрать все
Пример: href=aaa.php...<a href=index.php>Пример: href=aaa.php показывает...</a>Пример: href=aaa.php показывает...
 


Нужно найти фразы, начинающиеся на "href=" и заканчивающиеся на ".php", но только не те, что находятся внутри угловых скобок. Т.е. в данной строке нужно найти "href=aaa.php", но никак не "href=index.php". Опять не нашёл ничего лучшего, чем:
Код
Выбрать все
Set objRegExp = CreateObject("VBScript.RegExp")
objRegExp.Global = True
Str = "Пример: href=aaa.php...<a href=index.php>Пример: href=aaa.php показывает...</a>Пример: href=aaa.php показывает..."
objRegExp.Pattern = "(<[\s\S]*?>)|(href=[\s\S]*?\.php)"
Set objMatches = objRegExp.Execute(Str)
For Each objMatch In objMatches
    If Left(objMatch.Value, 1) <> "<" Then WScript.Echo objMatch.Value
Next
 


Довольно искусственно получается, должно быть более правильное решение наверное...
  
Наверх
www  
IP записан
 
kuntashov
Full Member
***
Отсутствует


1С:Специалист

Сообщений: 130
Местоположение: Саратов
Зарегистрирован: 13. Июня 2006
Пол: Мужской
Re: VBScript.RegExp: обрамляющие конструкции
Ответ #4 - 21. Августа 2007 :: 07:01
Печать  
А ты же сам меня однажды про look-ahead спрашивал, самое время их применить!  Подмигивание

Вот как-то так попробуй, хотя не уверен на 100% (сейчас проверить не могу):

Код
Выбрать все
objRegExp.Pattern = "(?:>[^><]*?)(href=[\s\S]*?\.php)" 



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

Либо, если модифицировать исходный документ не надо, еще проще: сохранить отрендеренный хтмл как текст, ну а потом - опять наши любимые регекспы.

То есть общий смысл - избавиться от необходимости обрабатывать хтмл-конструкции, т.к. с помощью регекспов это сложно, поскольку это не очень жесткий стандарт, к сожалению (вроде als - куда проще, да и с тем столько геморроя из-за его "непостоянства").
  

С уважением, &&Александр Кунташов&&http://kuntashov.ru/
Наверх
 
IP записан
 
The gray Cardinal
Full Member
***
Отсутствует



Сообщений: 159
Зарегистрирован: 17. Июня 2006
Пол: Мужской
Re: VBScript.RegExp: обрамляющие конструкции
Ответ #5 - 21. Августа 2007 :: 07:31
Печать  
Нет, это не совсем то.
Код
Выбрать все
Set objRegExp = CreateObject("VBScript.RegExp")
objRegExp.Global = True
Str = "Пример: href=aaa.php...<a href=index.php>Пример: href=aaa.php показывает...</a>Пример: href=aaa.php показывает..."
objRegExp.Pattern = "(?:>[^><]*?)(href=[\s\S]*?\.php)"
Set objMatches = objRegExp.Execute(Str)
For Each objMatch In objMatches
    WScript.Echo objMatch.Value
Next
 


Выдаёт:
Цитата:
>Пример: href=aaa.php
>Пример: href=aaa.php

Во-первых, найденное избыточно (фрагмент ">Пример: " лишний, нужно только "href=aaa.php").
Во-вторых, находит не всё (нужно найти все три вхождения).

На самом деле HTML приведён только для простоты примера, мы тут DDS парсить пытаемся Улыбка, но и это несущественно. Вопрос чисто "теоретический": как правильно парсить чёртовы обрамляющие конструкции? Просто хочется разобраться раз и навсегда Улыбка.

Напомни, что такое "look-ahead" вообще?...
  
Наверх
www  
IP записан
 
kuntashov
Full Member
***
Отсутствует


1С:Специалист

Сообщений: 130
Местоположение: Саратов
Зарегистрирован: 13. Июня 2006
Пол: Мужской
Re: VBScript.RegExp: обрамляющие конструкции
Ответ #6 - 21. Августа 2007 :: 07:48
Печать  
Нифига себе "для простоты примера" Улыбка))

Если предположить, что исходный документ синтаксически правилен, то самый простой алгоритм разбора парных конструкций - последовательный перебор открывающих/закрывающих элементов с отслеживанием текущего уровня либо в переменной (просто считая глубину), либо на стеке.

Регекспами универсальное ничего не напишешь. И теоретизировать на эту тему тяжеловато Улыбка

В als2xml (и некоторых других скриптах для ОпенКонфа) применялась схема "упрощения" синтаксиса исходного документа путем замены части конструкций (например парных кавычек в строке) на какой-то другой символ. Но все равно на 100% не избавляло от броблем.

DDS - это который
  

С уважением, &&Александр Кунташов&&http://kuntashov.ru/
Наверх
 
IP записан
 
The gray Cardinal
Full Member
***
Отсутствует



Сообщений: 159
Зарегистрирован: 17. Июня 2006
Пол: Мужской
Re: VBScript.RegExp: обрамляющие конструкции
Ответ #7 - 21. Августа 2007 :: 08:00
Печать  
Так я и не хочу универсальное писать! Я хочу просто понять, как правильно регэкспами работать с обрамляющими конструкциями. Просто если чуть что посложнее, то надо уже посимвольным перебором заниматься, что ли? Как-то это душу не греет... Нафига тогда спрашивается вообще регэкспы нужны? Они ведь и нужны типа для упрощения Улыбка. Вобщем, задача в общем виде звучит так:
1. Есть достаточно простой шаблон, вхождения которого надо найти.
2. Есть некие обрамляющие конструкции типа {\...\} или <...>, не суть важно.
3. Нужно найти все вхождения вышеупомянутого шаблона, находящиеся ВНЕ этих конструкций, неважно где.
Вот собственно и всё Улыбка.
  
Наверх
www  
IP записан
 
The gray Cardinal
Full Member
***
Отсутствует



Сообщений: 159
Зарегистрирован: 17. Июня 2006
Пол: Мужской
Re: VBScript.RegExp: обрамляющие конструкции
Ответ #8 - 21. Августа 2007 :: 08:05
Печать  
Вдогонку: можно конечно вначале найти все эти обрамляющие конструкции, повырезать их нафиг, а затем в оставшемся тексте найти уже свой шаблон. Но интуиция почему-то подсказывает мне, что настоящие пацаны так не делают Подмигивание, и есть более элегантный способ. Особенно, если текст, в котором ведётся поиск, велик по размеру...
  
Наверх
www  
IP записан
 
kuntashov
Full Member
***
Отсутствует


1С:Специалист

Сообщений: 130
Местоположение: Саратов
Зарегистрирован: 13. Июня 2006
Пол: Мужской
Re: VBScript.RegExp: обрамляющие конструкции
Ответ #9 - 21. Августа 2007 :: 08:15
Печать  
Предусматривает ли синтаксис исходного текста такую конструкцию как "строка"? Или - возможно ли использование обрамляющих конструкций не по прямому назначению?
  

С уважением, &&Александр Кунташов&&http://kuntashov.ru/
Наверх
 
IP записан
 
The gray Cardinal
Full Member
***
Отсутствует



Сообщений: 159
Зарегистрирован: 17. Июня 2006
Пол: Мужской
Re: VBScript.RegExp: обрамляющие конструкции
Ответ #10 - 21. Августа 2007 :: 08:27
Печать  
kuntashov писал(а) 21. Августа 2007 :: 08:15:
Предусматривает ли синтаксис исходного текста такую конструкцию как "строка"? Или - возможно ли использование обрамляющих конструкций не по прямому назначению?

Думаю, что на это пока закладываться не надо. Т.е. подразумевается, что все обрамляющие конструкции всегда парные и по-другому (например, в каких-то строковых константах) никогда не используются.
  
Наверх
www  
IP записан
 
trdm
1c++ power user
qt1l developer
1c++ moderator
Отсутствует



Сообщений: 2343
Местоположение: г. Ростов-на-Дону
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: VBScript.RegExp: обрамляющие конструкции
Ответ #11 - 21. Августа 2007 :: 08:46
Печать  
блин, большая разница чего парсить, для каждого "субъекта" лучше свой метод.
Если цель парсить DDS, то лучше уж построчный перебор ИМХО.
Он же не имеет "вложеный" т.с. тегов.
Он блочновнизспадающий )))
А парсить HTML, эту задачу лучше возложитьна эксплорер:
Код
Выбрать все
Sub MakeHelps2( psPath, psAllText)
	Set objIE = CreateObject("InternetExplorer.Application")
	objIE.Navigate psPath
	While objIE.Busy
	    Wscript.Sleep 200
	Wend

	set Document = objIE.Document
	set coll = document.all.tags("A")
	if Not IsObject(coll) Then
		exit sub
	end if
stop
	tPathDoc = Document.location.pathname
	' "/D:/Progekts/chm/OpenNET_docs/_%20No_CHM/autoconf-prog/index.html"
	tPathDocA = Split(tPathDoc,"/")
	tPathDoc1 = ""
	for i=1 To UBound(tPathDocA)-1
		tPathDoc1 = tPathDoc1 + tPathDocA(i) + "/"
	Next
	nnn = ""
	for i=0 to  coll.length-1
		set item = coll.item(i)
		nnn = nnn + item.title + vbcrlf
		'	item.href	aphy"	String
		'item.outerText	"Ссылки"	String
		'item.pathname	"D:/Progekts/chm/OpenNET_docs/_%20No_CHM/XML-web/index.html"	String
		' Мне нужен путь относительно переданного, но только файлы, следовательно:
		If Left(item.href,8) = "file:///" Then
			textRef = Replace(item.href,"file:///","")
			textRef = Replace(textRef, tPathDoc1,"")
			' теперь в textRef чистая ссылка...
			textTitle = item.outerText
			' и в принцыпе можно запускать генерацию текста
			psAllText = psAllText + GetTextArticle( textRef, textTitle, "	" )

		End If



	next
End Sub
 


+ полный скрипт: "Готовим файл "Table of Contents_.hhc" для "HTML Help Workshop""
  

zzCreate_Table_of_Contents_hhc.rar ( 2 KB | Загрузки )
Наверх
IP записан
 
trdm
1c++ power user
qt1l developer
1c++ moderator
Отсутствует



Сообщений: 2343
Местоположение: г. Ростов-на-Дону
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: VBScript.RegExp: обрамляющие конструкции
Ответ #12 - 21. Августа 2007 :: 08:57
Печать  
Цитата:
3. Нужно найти все вхождения вышеупомянутого шаблона, находящиеся ВНЕ этих конструкций, неважно где.
Вот собственно и всё Улыбка.

Собственно тогда тебе предстоит "Очистить" сорец от таких конструкций, и в нем тогда искать. Это если регекспами.
  
Наверх
IP записан
 
kuntashov
Full Member
***
Отсутствует


1С:Специалист

Сообщений: 130
Местоположение: Саратов
Зарегистрирован: 13. Июня 2006
Пол: Мужской
Re: VBScript.RegExp: обрамляющие конструкции
Ответ #13 - 21. Августа 2007 :: 09:49
Печать  
Код
Выбрать все
Set objRegExp = CreateObject("VBScript.RegExp")
objRegExp.Global = True
Str = "Пример1: href=aaa1.php...><a href=index.php>Пример2: href=aaa2.php показывает...</a>Пример3: href=aaa3.php показывает..."

'  вне конструкции, это значит, непосредственно слева от тебя - либо ничего, либо только закрывающая, а справа - ничего или открывающаяся, т.е. шаблон такой:
'  начало строки ИЛИ закрывающая - любые символы кроме открывающей - наша строка - любые символы, кроме закрывающей - открывающая ИЛИ конец строки
objRegExp.Pattern = "(^|>)[^<]*?(href=[^<>]*?\.php)[^>]*?(<|$)"

Set objMatches = objRegExp.Execute(Str)
For Each objMatch In objMatches
    WScript.Echo objMatch.Submatches(1)
Next
 



Результат:

     href=aaa2.php
     href=aaa3.php

первое вхождение не находит, потому что там синтаксическая ошибка: есть закрывающая конструкция, но нет парной открывающей
  

С уважением, &&Александр Кунташов&&http://kuntashov.ru/
Наверх
 
IP записан
 
artbear
1c++ developer
1c++ moderator
Отсутствует


Эх, дайте что-нибудь новенькое
да полезное потести

Сообщений: 6303
Местоположение: Москва
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: VBScript.RegExp: обрамляющие конструкции
Ответ #14 - 21. Августа 2007 :: 10:16
Печать  
В скрипте для Опенконфа - Поиск с помощью регулярных выражений
я ищу выражения в комментах и не в комментах вот так
Цитата:
' шаблон для поиска выражения, которое не встречается в комментариях 1C
' ^/?([^/]/?)*Выражение
' или
' ^(?!.*//).*Выражение
' Примечание: за уточнение спасибо mikeA и Номер 6 c Т1С
'
' шаблон для поиска выражения, которое, напротив, стоит в комментариях 1C
' //+.*Выражение

Это выдержка из скрипта Findtext.vbs
  

OpenConf developer :: http://openconf.1cpp.ru&&FormEx developer :: http://formex.dorex.ru&&1C++ active developer &amp;&amp; tester :: www.1cpp.ru
Наверх
GTalkSkype/VoIPICQ  
IP записан
 
Переключение на Главную Страницу Страницы: [1] 2 
ОтправитьПечать