Вход | Регистрация


Форумы на Кубань.Ру


1С:Предприятие ::

Метки:

Соответствие строки определенной маске...

Ø
Я
   pat
20.11.00 - 22:58
Что-то не получается придумать нормальный алгоритм для определения соответствие строки определенной маске (например, *рыо????вап*фыв?*). Между тем, должно быть, в программистской практике это известная задачка.
Может кто в курсе (и/или башковитый)?
Прошу простить, если такие темы в этом форуме не приветствуются...
 
  Рекламное место пустует
   max
1 - 21.11.00 - 06:09
А шаблон пробовал? Хотя для чего тебе, ума не приложу! ;))
   pat
2 - 22.11.00 - 11:25
Нет, шаблон() - это не то...
Пишу мини-поисковик (внутри-1с-овский). Нужна функция, которая проверяет на соответствие входящей строки определенной маске (как везде).
   ShAM
3 - 22.11.00 - 11:48
Если описать это - *рыо????вап*фыв?* - словами, то получится наверное так
1. Ищем первое вхождение "рыо"
2. Через 4 символа должно находится "вап"
3. В оставшейся строке должен находиться "фыв", но обязательно с любой буквой.
Алгоритм тоже не сложный.
1. Проверяем первый символ в строке на "стоп-символ".
2. В зависимости от него делаем некоторые действия (например, если "*" - берем следующий, проверяем и либо пишем в шаблон поиска, либо что-то делаем со строкой поиска). И т.д.
3. п.2 идет в цикле. На самом деле условий не много их можно систематизировать.
Готового алгоритма нет. Но мысль интересная для свободного времени.
Да, в 1С это работа с Найти(), Сред(), Лев()
   gosha
4 - 22.11.00 - 12:07
Ищи в Архивах!... там длинный флейм про "парсить строки..." был!...
   Татарин
5 - 22.11.00 - 12:13
Насчет алгоритма. Практически придется писать что-то типа интерпритатора...
Т.е. синтаксический разбор маски (лексический анализ может тоже отдельно сделать?) и потом... Интересно, мля. Напишу на досуге, молодость вспомню. Сейчас некогда :((
   pat
6 - 23.11.00 - 10:59
Всем спасибо. To gosha - прямым поиском "парсить" не нашел, но обязательно покопаюсь. Но задача же решается настолько часто, что, чую, есть что-то готовое. Если не найду, напишу и выложу...
   mpashka
7 - 23.11.00 - 12:14
pat.
Если нужен универсальный поиск в 1С (через метаданные и как внешний отчет), то вышлем?
Пиши на mpa@ingr.cn.ua
   mpashka
8 - 23.11.00 - 12:15
... поиск с масками и т.д.
   Татарин
9 - 23.11.00 - 13:22
написал.Как обещал.Строго не судите.
//*******************************************
Функция Автомат(Знач Стр,Знач Шаб,Знач Лекс=999)
Пока СтрДлина(Шаб)>0 Цикл
		Если Число(Лекс)=999 Тогда
			Лекс1=Лев(Шаб,1);
			Шаб=Прав(Шаб,СтрДлина(Шаб)-1);
			Возврат Автомат(Стр,Шаб,Лекс1);
		ИначеЕсли Лекс="*" Тогда
			Лекс1=Лев(Шаб,1);
			Шаб=Прав(Шаб,СтрДлина(Шаб)-1);
			Если Лекс1="?" Тогда
				Пока СтрДлина(Стр)>0 Цикл
					Стр=Прав(Стр,СтрДлина(Стр)-1);
					Если Автомат(Стр,Шаб)=1 Тогда
						Возврат(1);
					КонецЕсли;
				КонецЦикла;
				Возврат(0);
			ИначеЕсли Лекс1="*" Тогда
				Возврат Автомат(Стр,Шаб,Лекс1);
			Иначе
   				НомерПозиции=Найти(Стр,Лекс1);
				Пока НомерПозиции<>0 Цикл
					Стр=Прав(Стр,СтрДлина(Стр)-НомерПозиции);
					Если Автомат(Стр,Шаб)=1 Тогда
						Возврат(1);
					КонецЕсли;
					НомерПозиции=Найти(Стр,Лекс1);
				КонецЦикла;
				Возврат(0);
			КонецЕсли;
		ИначеЕсли Лекс="?" Тогда
			Если СтрДлина(Стр)=0 Тогда
				Возврат(0);
			КонецЕсли;
			Стр=Прав(Стр,СтрДлина(Стр)-1);
			Возврат Автомат(Стр,Шаб);
		Иначе
			Если Лекс<>Лев(Стр,1) Тогда
				Возврат (0);
			Иначе				//				Шаб=Прав(Шаб,СтрДлина(Шаб)-1);
				Стр=Прав(Стр,СтрДлина(Стр)-1);
				Возврат Автомат(Стр,Шаб);
			КонецЕсли;
		КонецЕсли;		
	КонецЦикла;
	Если Лекс="*" Тогда
		Возврат(1);
	ИначеЕсли Лекс=999 Тогда
		Если СтрДлина(Стр)>0 Тогда
			Возврат(0);
		КонецЕсли;
	ИначеЕсли (Лекс="?") И (СтрДлина(Стр)=1) Тогда
		Возврат(1);
	ИначеЕсли (Лекс=Лев(Стр,1)) И (СтрДлина(Стр)=1) Тогда
		Возврат(1);
	Иначе
		Возврат(0);
	КонецЕсли;
КонецФункции
Функция Удовлетворение(Знач ИсходнаяСтрока,Знач ШаблонСтроки)
// УдоВлетворение возвращает 1 - если ИсходнаяСтрока удовлетворяет
// ШаблонуСтроки, иначе 0// В шаблоне- любые символы.
//"?" - один произвольный символ//"*" - несколько произвольных символов от 0 до ...
//пустому шаблону не удовлетворяет никакая Исходная строка//если есть желание в пустой Шаб можете добавить "*"(тогда люб.строка удовлетворит)
	Стр=СокрП(ИсходнаяСтрока);
    Шаб=СокрП(ШаблонСтроки);
    Возврат Автомат(Стр,Шаб);
КонецФункции
   Татарин
10 - 23.11.00 - 13:48
Вдогонку. Сделал в 7.5 :[ . Надеюсь, в 7.7 пойдет :)
 
 
   Mazzy
11 - 23.11.00 - 14:32
Занимательно...
Можно даже сказать, неплохо (судя по внешнему виду)...
Будет работать медленно (судя по тому же внешнему виду). Очень медленно. Строковые функции на внутреннем языке работают очень медленно. Поэтому практическое использование в 1С - достаточно спорно.
Но сделано красиво.
.
Непринципиальное замечание: лучше проверять не на =999, а на >=999. И вообще использовать не 9999, а более безопасное 99999 (это число превышает 0xFFFF). Но... неаккуратненько.
.
Принципиальное замечание: разбор шаблона ведется в момент сравнения. Это сильно замедляет сравнение при пакетном сравнении (например, найти элементы справочника по одной маске). Поэтому парсер маски и сравниватель хорошо бы разнести на две процедуры.
.
В результате приходим к сложности хранения сложных структур в 1С... и... к тому, что эту задачу лучше не делать на бейсикоподобных языках со сборкой мусора. На таких языках строковые функции принципиально неторопливы.
.
А в остальном, красиво.
   Mazzy
12 - 23.11.00 - 14:41
Раз уж начал :-)
.
Передача по значению в Автомат в данном случае не оптимальна. Экспортируемая функция Удовлетворение. Там и нужен Знач. А в Автомат Знач только забивает стек (в Автомат старое Стр и Шаб не используются).
.
Согласен сейчас Автомат безопаснее в случае, если его вызовет пользователь, но на длинных строках стек может переполнится.
.
СтрДлина(Шаб), СтрДлина(Стр) используются достаточно часто. Их можно было бы вынести в локальные переменные.
.
Лекс используется как число (999) и как символ "*","?". Виноват, не разобрался сразу. Стоит ли так?
.
Надо будет вечером попробовать шаблон "**". По-моему, будут глюки.
Очень занимательная процедура!!!
Спасибо.
   Василий
13 - 23.11.00 - 14:45
 зайдите на http://www.kuban.ru/cgi-bin/forum/forum9.cgi?page=1&ask=6124 там ответ.
   Mazzy
14 - 23.11.00 - 15:09
Василий, а можно название этого топика? А то, похоже, он ушел с первой страницы.
   TeNTeN
15 - 23.11.00 - 15:17
Для (14): "Внешние компоненты для 1С на заказ".
   Mazzy
16 - 23.11.00 - 15:32
:-)
Спасибо
   Татарин
17 - 23.11.00 - 15:58
to Mazzy. Со всем, в принципе, согласен. Но вот насчет передачи по значению... Из-за "*" все это(будь она неладна!)! Т.е. шаблон="1*56",
строка="1фыв56цйуцйу56". Так вот, если мы будем курочить сам шаблон, то получим то, что эта строка неудовлетворяет шаблону.
   WildHare
18 - 23.11.00 - 16:14
А если использовать для обработки и анализа строк внешнее приложение? Perl, например? Он именно для таких вещей и предназначен.
   Mazzy
19 - 23.11.00 - 16:26
К 17: Татарин, дак и оставляй Знач только у шаблона. Бог с ним. Ты у себя шаблон "**" проверить можешь? Сейчас у меня руки заняты :-)
.
К 18: WildHare, Perl - можно, для доступа к DBF - ODBC, для работы с текстом - Word, для работы с формами - Explorer объекты.
Идея хорошая - на практике что-то не очень получается :-)
.
Все-таки такие задачи при всей неприменимости в реальной жизни - хороший материал для тренировки :-)
   WildHare
20 - 23.11.00 - 16:33
2Mazzy
Я знаю, что хороший, периодически сам занимаюсь подобными вещами. Но уж больно муторно на 1С делать анализ текста, не только для программиста муторно, но и для процессора..
   Mazzy
21 - 23.11.00 - 16:37
Согласен.
   Татарин
22 - 23.11.00 - 17:44
To Mazzy. Извини за задержку - сервер. "**" нормально работает. Насчет передачи по значению Стр такой вариант: шаблон="1*56?78" , строка="1рпа5656р78" - искурочим строку и результат - неудовлетворяет(хотя оченно даже удовлетворяет).
ЗЫ Проверил-точно, нельзя по ссылке!
Да. На Си я писал интерпретатор(давным-давно). Там, конечно, такие вещи писать просто в кайф!
   Татарин
23 - 23.11.00 - 17:51
to pat. А ты-то что молчишь? :)
   pat
24 - 23.11.00 - 22:20
Молчал из оффлайна (инет дома юзаю). To Татарин - зд0рово! (правда на строку="qwerty asd qwerty11" и маску="*qwerty*qwerty*?" выдает 0).
  То Василий - понял: внешняя компонента - оптимальное решение. Хотя в данном случае скорость не критична - вполне подойдет "Автомат(Стр,Шаб)" (Узкое место в другом:)))
   pat
25 - 23.11.00 - 22:25
То Василий - спасибо :)(забыл сказать)
   pat
26 - 23.11.00 - 22:31
То Татарин - спасибо :)(забыл сказать)
   Mazzy
27 - 24.11.00 - 09:03
К 24, 9: Алгоритм не совсем корректно отрабатывает ? после *. Т.е. шаблон "*?" работает не совсем хорошо. Шаблон "*?текст" - нормально.
.
К 22: Да "**" работает, спасибо. Неточность чуть выше. Там где ? обрабатывается после *. Опшипся я.
.
Татарин, красиво. Но... Рекурсивные алгоритмы хорошо работают в тех случаях когда состояние на итерации хорошо и однозначно выводится из состояния на предыдущей итерации И не зависит от следующего состояние. Шаблон - не из этого случая.
.
Значение символа в шаблоне сильно зависит от контекста. Значение символа зависит не только от предыдущих символов, но и от символов, расположенных после текущего. Поэтому рекурсивный алгоритм в данном случае не совсем хорош.
.
И-эх, зацепил, Татарин... Зацепил...
Хочу написать статейку по этому поводу. Цель - не столько расписать алгоритм поиска, сколько поррасуждать на тему (старею что ли?) как писать алгоритмы, делать их расширяемыми и о особенностях 1Сика... Можно я использую текст твоего алгоритма и укажу твое ник/имя/адрес? Можешь мне написать?
.
В статейке хочу привести свой прототип алгоритма поиска.
Функция Поиск_РазборШаблона(Шаблон="")// возвращает план выплонения
Функция Поиск_ОптимизацияПланаВыполнения(План)
Функция Поиск_ПоГотовомуПлану(Стр,План)
Функция Поиск(Стр,Шаблон)
.
Если успею за выходные, попробую расписать как тоже самое делается на других языках (не 1Сик).
.
Ну как, Татарин, напишешь?
   Mazzy
28 - 24.11.00 - 09:04
В смысле, дашь разрешение на использование?
   Татарин
29 - 24.11.00 - 09:03
to pat(24). Да. Неправильно работало. Если хочешь, могу мылом .ert сбросить.
Надо исправить в Автомат()в конце, после всех циклов :
	Если Лекс="*" Тогда
		Возврат(1);
	ИначеЕсли Лекс=999 Тогда
		Если СтрДлина(Стр)>0 Тогда
			Возврат(0);//..
// вот эти две строчки
		Иначе
			Возврат(1);//..
		КонецЕсли;
to All. Я не ставил целью оптимальность работы данной функции ни по скорости ни по памяти. Просто сделал чтоб работало. Спасибо за участие!
   Mazzy
30 - 24.11.00 - 09:08
Спасибо. Если можно пришли свой ert.
.
Согласен, На 1С такая вещь будет работать медленно, как ее ни реализуй. Говорю же, это скорее методическая задача для обучения и тренировки. В реальной жизни, на тех средствах, что имеем, ее вряд ли можно использовать.
.
Может я ошибаюсь, но мне показалось, что ты несколько обиделся. Извини, если так. Твой алгоритм действительно красив. Некоторые неточности можно исправить. Главное, его можно использовать, если есть необходимость. pat спросил - ты ответил.
.
Твой алгоритм хочется использовать в пункте "как разбираться в чужой программе". Поставленная задача четкая обозримая и интуитивно понятная, алгоритм небольшой, но достаточно сложный - отличный методический пример.
.
Еще раз спасибо за адрес.
   pat
31 - 24.11.00 - 11:55
То Татарин 29. Вышли пожалуйста - шестьдесят строк логических выражений трудны для восприятия :).
   pat
32 - 24.11.00 - 12:38
Что-то и мне захотелось такую написать. Получилось не так красиво, но работает в двое быстрей (ни в коем случае не вые...сь)... Все равно около 30 сек на 10000 операций Автомат("рqwerty asd qwerty15","*qwerty*??qw??ty**??")
Функция Автомат(Знач ИсходнаяСтрока,Знач ШаблонСтроки)
	Ш=""""+ШаблонСтроки+"""";
	ш=стрЗаменить(ш,"*",""",""");
	ш=стрЗаменить(ш,"?",""",""?"",""");
	спСлов=СоздатьОбъект("СписокЗначений");
	спСлов.ИзСтрокиСРазделителями(ш);
	Для Сч=1 По спСлов.РазмерСписка() Цикл
		Слово=спСлов.ПолучитьЗначение(Сч);
		Если ПустаяСтрока(Слово)=1 Тогда
		    Продолжить;
		КонецЕсли;
		ДлинаСтроки=СтрДлина(ИсходнаяСтрока);
		ДлинаСлова=СтрДлина(Слово);
		Если (ДлинаСтроки>0) Тогда
			Если Слово="?" Тогда
				ИсходнаяСтрока=Сред(ИсходнаяСтрока,2);
			Иначе
				Поз=Найти(ИсходнаяСтрока,Слово);
				Если Поз>0 Тогда
					ИсходнаяСтрока=Сред(ИсходнаяСтрока,Поз+ДлинаСлова);
				Иначе
					Возврат 0;
				КонецЕсли;
			КонецЕсли;
		Иначе
			Возврат 0;
		КонецЕсли;
	КонецЦикла;
	Возврат 1;
КонецФункции
   Татарин
33 - 24.11.00 - 13:38
to pat. Проверил. Все хорошо, но любая строка "556"+произвольнаяСтрока удовлетворяет шаблону="5*5"
 :( . Что-то с обработкой в конце.
Но путь, конечно более верный. Отлично! Тут мне свою функцию куда подальше...
Посмотрю, может доделаю :)
 
 
   pat
34 - 24.11.00 - 14:25
Я тоже подумал об этом, но это разное понимание "соответствия". Например, Нортон при поиске файла "command" или *command*.* найдет command.com. Если "command" не должен соответствовать "command.com", то в конце функции необходимо добавить что-то вроде (вместо Возврат 1):
Если СтрДлина(ИсходнаяСтрока)>0 Тогда
Возврат 0
Иначе
Возврат 1
КонецЕсли;//не проверено - не отвечаю
   Татарин
35 - 24.11.00 - 14:46
to pat. Ты уж извини, продолжу :)
строка="1234567890" удовлетворяет шаблону="5" :(
Доделаем. Все равно путь верный.
; )
   pat
36 - 25.11.00 - 11:35
Не хочу показаться нудным, но строка="1234567890" действительно удовлетворяет шаблону="5". Пример: в окнах грим пуск=>найти, пишем "omman" - и в результатах находим и command.com и проч.
Однако, если строка="1234567890" не должна удовлетворять шаблону="5" (а только "*5*"), то надо добавить стоп-символ справа и слева и к строке и к шаблону.
Готовая для жизни функция:
Функция Автомат(Знач ИсходнаяСтрока,Знач ШаблонСтроки, Знач Парам=0)
	Симв127=Симв(127);
//Защита ковычек, запятых, и доллара
	ИсходнаяСтрока=стрЗаменить(ИсходнаяСтрока,"""",Симв127);
	ИсходнаяСтрока=стрЗаменить(ИсходнаяСтрока,",",Симв127);
	ИсходнаяСтрока=стрЗаменить(ИсходнаяСтрока,"$",Симв127);
	ШаблонСтроки=стрЗаменить(ШаблонСтроки,"""",Симв127);
	ШаблонСтроки=стрЗаменить(ШаблонСтроки,",",Симв127);
	ШаблонСтроки=стрЗаменить(ШаблонСтроки,"$",Симв127);
	Если Парам=1 Тогда//добавляем стоп-символы
		ШаблонСтроки="$"+ШаблонСтроки+"$";
		ИсходнаяСтрока="$"+ИсходнаяСтрока+"$";
	КонецЕсли;
	Ш=""""+ШаблонСтроки+"""";
	ш=стрЗаменить(ш,"*",""",""");
	ш=стрЗаменить(ш,"?",""",""?"",""");
	спСлов=СоздатьОбъект("СписокЗначений");
	спСлов.ИзСтрокиСРазделителями(ш);
	Для Сч=1 По спСлов.РазмерСписка() Цикл
		Слово=спСлов.ПолучитьЗначение(Сч);
		Если ПустаяСтрока(Слово)=1 Тогда
		    Продолжить;
		КонецЕсли;
		ДлинаСтроки=СтрДлина(ИсходнаяСтрока);
		ДлинаСлова=СтрДлина(Слово);
		Если (ДлинаСтроки>0) Тогда
			Если Слово="?" Тогда
				ИсходнаяСтрока=Сред(ИсходнаяСтрока,2);
			Иначе
				Поз=Найти(ИсходнаяСтрока,Слово);
				Если Поз>0 Тогда
					ИсходнаяСтрока=Сред(ИсходнаяСтрока,Поз+ДлинаСлова);
				Иначе
					Возврат 0;
				КонецЕсли;
			КонецЕсли;
		Иначе
			Возврат 0;
		КонецЕсли;
	КонецЦикла;
	Возврат 1
КонецФункции
   VBScript
37 - 25.11.00 - 14:48
Ребята была тут идея использовать внешние компоненты, так зачем городить огород МелкоСофт уже все до нас придумала. Привожу один пример(правда на Дельфи, но если 1Сик мозги не отбил, то желающие на него переведут). Итак, соответствие выражения шаблону.
...
var
 RegExp : variant;
begin
 RegExp:=CreateOLEObject('VBScript.RegExp');
 RegExp.pattern:='\w+\@[.\w]+';
 if RegExp.Test(Edit1.Text) Then
  ShowMessage('Mail adress Ok');
 Else
  ShowMessage('Mail adress BAD');
 end;
...
1C поддерживает OLE, требуется только установленный IE 5.0 (и вообще там еще много чего напихано подобного, надо только посмотреть)
   pat
38 - 25.11.00 - 20:11
To 37. Very thanks. Да где ж ты был... те же 10000 операций выполняются таким образом за 2 с. Сообщи, plz, где прочитать про синтаксис "pattern"'a.
   Молодой
39 - 25.11.00 - 21:22
Для 37 VBScript
 - обяъсните "чайнику" как то, что написано к 1с "прикрутить"?
   VBScript
40 - 25.11.00 - 21:48
Рад что помогло. Вообще в последнее время, если чего не могу сделать на 1С так и не ломаю голову. Немного поковырялся в сети и вот тебе ActiveX-компонента - делай что надо. А если не получилось найти так можно и на C++ Builder или Delphi наваять по-быстрому. А почитать про все это хозяйство можно конечно же у все того же МелкоСофта, начни с http://msdn.microsoft.com/scripting/default.htm, выбери VBScript,затем Regular Expressions Guide, и далее Regular Expressions Syntax.
Будет желание пообщаться,пиши.
   VBScript
41 - 25.11.00 - 22:41
Ну нельзя же быть такими ленивыми, а впрочем пока самого не клюнет...
Перевод с нормального на 1Сик
...
RegExp=СоздатьОбъект("VBScript.RegExp");
RegExp.pattern="\w+\@[.\w]+";
Если RegExp.Test(Adress)=(-1) тогда
    Предупреждение("Похоже на e-mail адрес");
Иначе
    Предупреждение("Не, это что-то не то");
КонецЕсли;
...
предназначено сие для проверки соответствия введенного значения (Adress) шаблону адреса электронной почты (наличие @, буквы, и т.п.).
Кстати можно IE 5.0 и не ставить, а просто обновить с сайта Microsoft скриптовый язык VBScript до версии 5.0
   Молодой
42 - 26.11.00 - 13:27
VBScript, спасибо большое. Читаю...
   Mazzy
43 - 27.11.00 - 13:36
Мда. Действительно занятная весчь. Спасибо, VbSript. Надо будет протестировать.
.
Я тоже написал обработку и выложил первые результаты. Если есть желание, то можно посмотреть на http://www.user.cityline.ru/~fbmazs/exercise/1Cgrep.htm.<br>Замечания и исправления приветствуются.
.
В следующие выходные попробую протестировать и сравнить со скриптовым поиском.
   VBScript
44 - 27.11.00 - 19:23
для Mazzy: Серега, ты молодец, нам бы такой подход (это я ссылочку твою глянул), как допишешь свисти, покалякаем.
   pat
45 - 28.11.00 - 11:08
to Mazzy. Вот так ссылочка! Академический подход - класс.




Список тем форума

Форум Территория 1С

Рекламное место пустует   Рекламное место пустует
ВНИМАНИЕ! Если вы потеряли окно ввода сообщения, нажмите Ctrl-F5 или Ctrl-R или кнопку "Обновить" в браузере.
Ветка сдана в архив. Добавление сообщений невозможно.
Но вы можете создать новую ветку и вам обязательно ответят!
Каждый час на Волшебном форуме бывает более 2000 человек.
Рекламное место пустует