Имя: Пароль:
1C
 
Функция поиска по шаблону с использованием звездочки.
0 ZveZda
 
09.01.06
13:47
Добрые, Гуру. Не поделитесь функцией/ями поиска (для 7.7) строки из списка строк по шаблону с использованием символа '*' (например: "*круг*45*ST*")?
Пожалуйста.
1 Иде я
 
09.01.06
13:54
Тока если напрямую через SQL...
LIKE
Determines whether or not a given character string matches a specified pattern. A pattern can include regular characters and wildcard characters. During pattern matching, regular characters must exactly match the characters specified in the character string. Wildcard characters, however, can be matched with arbitrary fragments of the character string. Using wildcard characters makes the LIKE operator more flexible than using the = and != string comparison operators. If any of the arguments are not of character string data type, Microsoft® SQL Server™ converts them to character string data type, if possible.

Syntax
match_expression [ NOT ] LIKE pattern [ ESCAPE escape_character ]

Arguments
match_expression

Is any valid SQL Server expression of character string data type.

pattern

Is the pattern to search for in match_expression, and can include these valid SQL Server wildcard characters.

Wildcard character Description Example
% Any string of zero or more characters. WHERE title LIKE '%computer%' finds all book titles with the word 'computer' anywhere in the book title.
_ (underscore) Any single character. WHERE au_fname LIKE '_ean' finds all four-letter first names that end with ean (Dean, Sean, and so on).
[ ] Any single character within the specified range ([a-f]) or set ([abcdef]). WHERE au_lname LIKE '[C-P]arsen' finds author last names ending with arsen and beginning with any single character between C and P, for example Carsen, Larsen, Karsen, and so on.
[^] Any single character not within the specified range ([^a-f]) or set ([^abcdef]). WHERE au_lname LIKE 'de[^l]%' all author last names beginning with de and where the following letter is not l.


escape_character

Is any valid SQL Server expression of any of the data types of the character string data type category. escape_character has no default and must consist of only one character.
2 Иде я
 
09.01.06
13:56
Ну а так теоретически.
Разбирай шаблон.
Все что между звездочек в список значений или еще куда.
И ищи фхождение кадой подстроки.
Если вошли все подстроки и они не пересекаются и последовательно - самое оно...
3 Иде я
 
09.01.06
13:56
Думаю тока через перебор можно реализовать - если не изврящаться
4 skunk
 
09.01.06
14:11
//*******************************************
function strSearchPattern(strSource, strTempate)
   strTempate = """" + strreplace(strTempate, "*", """,""") + """";
   vlTemp = createobject("valuelist");
   vlTemp.FromSeparatedString(strTempate);
   Answer = "yes";
   intCount = vlTemp.GetListSize();
   for x = 1 to intCount do
       strValue = vlTemp.GetValue(x);
       if isblankstring(strValue) = 0 then
           intPos = find(strSource, strValue);
           if intPos = 0 then
               Answer = "no";
               break;
           endif;
           strSource = right(strSource, strlen(strSource) - intPos - strlen(strValue));
       endif;
   enddo;
   return Answer;
endfunction

message(strSearchPattern("наждачный круг диаметром 45 фирмы ST GBh", "*круг*45*ST*"));
message(strSearchPattern("ST GBh наждачный круг диаметром 45 фирмы", "*круг*45*ST*"));
5 Барбариска
 
09.01.06
14:44
(4) контрпример - строки-маски, содержащие "" и , -  например, 111113","322222 и *1","2* - выдает соответствие маске, которого нет. Это все из-за того, что вСтрокуСРазделителями работает не так, как хотелось бы ))
Моя функция - более длинная, но работает правильнее ))

Функция СоответствиеМаске(Стр,Маска,СУчетомРегистра=0) Экспорт  // Natalia
// Стр - строка, для которой проверяем соответствие маске
// Маска - собственно маска!
// СУчетомРегистра=0 - игнорируется различие между большими и маленькими буковками

ННом1=СокрЛП(Стр); ННом2=СокрЛП(Маска);

Если СУчетомРегистра=0 Тогда
 ННом1=ВРег(ННом1); ННом2=ВРег(ННом2);
КонецЕсли;
// удалим повторные звездочки
Пока Найти(ННом2,"**")>0 Цикл
 ННом2=СтрЗаменить(ННом2,"**","*");  
КонецЦикла;

Пока Найти(ННом1,"**")>0 Цикл
 ННом1=СтрЗаменить(ННом1,"**","*");  
КонецЦикла;


Если Найти(Нном2,"*")=0 Тогда
 Если ННом1=ННом2
 Тогда Возврат 1
 Иначе Возврат 0
 КонецЕсли;    
КонецЕсли;  

СпЗвездочек=СоздатьОбъект("СписокЗначений");
СпКусочков=СоздатьОбъект("СписокЗначений");

Дл=СтрДлина(ННом2);  
Н2=Нном2;
//рассчитаем позиции звездочек - т.е. между любыми двумя звездочками будут символы
Для сч=1 по Дл Цикл
   Поз=Найти(Н2,"*");
   Если Поз>0 Тогда
     СпЗвездочек.ДобавитьЗначение(Поз);  
     Н2=Лев(Н2,Поз-1)+"+"+Прав(Н2,СтрДлина(Н2)-Поз);
   Иначе
     Прервать;
   КонецЕсли;
КонецЦикла;    

Поз1   =СпЗвездочек.ПолучитьЗначение(1);
ПозПосл=СпЗвездочек.ПолучитьЗначение(СпЗвездочек.РазмерСписка());

Если Поз1<>1 Тогда // проверяем строгое соответствие начала
Кус1=Лев(ННом1,Поз1-1);  
Кус2=Лев(ННом2,Поз1-1);
Если Кус1<>Кус2 Тогда Возврат 0 КонецЕсли;
КонецЕсли;
Если ПозПосл<>СтрДлина(ННом2) Тогда
//если после звездочки больше нет символов - проверяем строгое соответсвие хвостов
ДлинаКус=СтрДлина(ННом2)-ПозПосл;
Кус1=Прав(ННом1,ДлинаКус);
Кус2=Прав(ННом2,ДлинаКус);
Если Кус1<>Кус2 Тогда Возврат 0 КонецЕсли;
КонецЕсли;

// рассчитаем кусочки "от звездочки до звездочки"
Для сч=1 по СпЗвездочек.РазмерСписка() Цикл
  Поз=СпЗвездочек.ПолучитьЗначение(сч);
 
  Попытка Поз1=СпЗвездочек.ПолучитьЗначение(сч+1);
  Исключение Прервать КонецПопытки;
  Поз=Поз+1;
  Кусочек=Сред(ННом2,Поз,Поз1-Поз);        
  СпКусочков.ДобавитьЗначение(Кусочек); // разбили маску на кусочки между звездочками
КонецЦикла;    

Н1=ННом1;
Для сч=1 по СпКусочков.РазмерСписка() Цикл
 Зн=СокрЛП(СпКусочков.ПолучитьЗначение(сч));
 Поз=Найти(Н1,Зн);  
 Если Поз=0 Тогда Возврат 0 КонецЕсли; // нет такого кусочка!
 Поз1=Поз-1+СтрДлина(Зн);
 Н1=Прав(Н1,СтрДлина(Н1)-Поз1);
КонецЦикла;    
Возврат 1;
КонецФункции
6 skunk
 
09.01.06
14:48
(4)легко устраняется ... одной строчкой... спасибо, что напомнила... всегда забываю ;))


//*******************************************
function strSearchPattern(strSource, strTempate)
   strTempate = strreplace(strTempate, """", """""");
   strTempate = """" + strreplace(strTempate, "*", """,""") + """";
   vlTemp = createobject("valuelist");
   vlTemp.FromSeparatedString(strTempate);
   Answer = "yes";
   intCount = vlTemp.GetListSize();
   for x = 1 to intCount do
       strValue = vlTemp.GetValue(x);
       if isblankstring(strValue) = 0 then
           intPos = find(strSource, strValue);
           if intPos = 0 then
               Answer = "no";
               break;
           endif;
           strSource = right(strSource, strlen(strSource) - intPos - strlen(strValue));
       endif;
   enddo;
   return Answer;
endfunction

message(strSearchPattern("наждачный ""круг"" диаметром 45 фирмы ST GBh", "*круг""*45*ST*"));
message(strSearchPattern("ST GBh наждачный круг диаметром 45 фирмы", "*круг*45*ST*"));
7 Simod
 
09.01.06
16:03
8 skunk
 
09.01.06
16:21
(7)там слишком грузно для (0) ... да аффтор видать спекся уже...
9 Simod
 
09.01.06
16:26
(8) Да я думаю, что всем пригодится.
10 insider
 
09.01.06
16:29
Кому RegExp не угодил? Хотя придумывать велик - занятие безусловно увлекательное...
11 skunk
 
09.01.06
16:39
(9)не думаю... хотя это мое мнение...

(10)по подробней пожалуйста?
12 insider
 
09.01.06
16:42
(11) RegEx=CreateObject("VBScript.RegExp");
    RegEx.Pattern=TrimAll(Pattern);
ну и т.д., подробнее на сайте некрупных и мягких
13 skunk
 
09.01.06
16:49
(12)да старость не в радость... забыл (((
14 insider
 
09.01.06
16:55
+12 например:
есть справочник "ТМЦ", в нем компьютерные "запчасти", будем искать по шаблону:

RegEx=СоздатьОбъект("VBScript.RegExp");
   RegEx.Pattern=СокрЛП(Pattern);
   Спр=СоздатьОбъект("Справочник.ТМЦ");
   Спр.ВыбратьЭлементы(0); к=0;
   Пока Спр.ПолучитьЭлемент() = 1 Цикл
       Если Спр.ЭтоГруппа()=1 Тогда
           Продолжить;
       КонецЕсли;
       //RegEx.Test(Спр.Наименование);
       mc=RegEx.Execute(Спр.Наименование);
       if mc.Count()>0 then
           //Сообщить(Спр.Наименование,"i");  
           к=к+1; стр="";
           for i=0 to mc.Count()-1 do
               //Сообщить(mc.Item(i).value);    
               for j=0 to mc.Item(i).SubMatches.Count()-1 do
                   //Сообщить(mc.Item(i).SubMatches(j));
                   стр=стр+"   "+mc.Item(i).SubMatches(j)
               enddo;
           enddo;
           Сообщить(Формат(Спр.Наименование,"С100")+": "+стр,"i");
       endif;
   КонецЦикла;  
   Сообщить("Всего: "+к);          
   
//***Примеры паттернов
// Винчестер.*(Serial ATA) - ищем все саташные винты
//Процессор Athlon|Sempron - ищем только Атлоны и Семпроны
//RegEx.Pattern="Процессор.*(s\d{3})";  - ищем процессор с тремя цифирками в номере сокета (число ножек т.е.), типа s478 и т.п.
// (\d{1,}[.,]?\d{0,3}GHz)  - ищем все, где есть упоминания о GHz, начинается все это с числа, причем разделитель целой части может быть точка или запятая
// Процессор (IP\sXEON|IP\w{0,1}|Celeron\s{0,1}\w{0,1}) (s\d{3}|LGA \d{3})? (Box)? (\d{1,}[.,]?\d{0,3}G+) - ищем все процессоры, а именно при, ксеоны, целики, боксовые и не только...
// Процессор (IP\sXEON|IP\w{0,1}|Celeron\s{0,1}\w{0,1}) (s\d{3}|LGA \d{3})? (Box)? (\d{1,}[.,]?\d{0,3}G(?:Hz)?) - примерно то же, но обозначение частоты может оканчиваться на "G", опционально на "GHz"
15 insider
 
09.01.06
16:55
ужасно отформатировалось :( надеюсь разберетесь
16 lisss
 
10.01.06
13:25
//******************************************************************************
// Возвращает 1, если строка соответствует шаблону,
//   или 0, если не соответствует
//
//  Параметры:   Стр1 - строка, Стр2 - шаблон(с использованием "*"),
//                                    Рег - 1 (с учетом регистра) или 0 (без учета регистра)  
//
//  Примечание: если Стр1 или Стр2 будут иметь пустое значение,
//                                          функция возвращает 0
//                                          количество "*" ограничено количеством записей
//                                          в массиве СпЗ (100)
//
Функция НайтиПоШаблону(Стр1="",Стр2="",Рег=1)  
   Перем СпЗ[100];      
   
   Если (Стр1 = "") или (Стр2 = "") Тогда
           Возврат(0);
   КонецЕсли;        
   
   Если Рег = 0 Тогда
       Ст1 = Стр1;
       Ст2 = Стр2;          
   Иначе
       Ст1 = ВРег(Стр1);
       Ст2 = ВРег(Стр2);  
   КонецЕсли;    
   
   Пока Найти(Ст2,"**")<>0 Цикл
       Ст2 = СтрЗаменить(Ст2,"**","*")
   КонецЦикла;                
   
   n = 0;
   Пока Ст2<>"" Цикл      
       n = n+1;
       k = Найти(Ст2,"*");
       k = ?(k>0,k,СтрДлина(Ст2)+1);            
       СпЗ[n] = Лев(Ст2,k-1);  
       Ст2 = Прав(Ст2,СтрДлина(Ст2)-k)    
   КонецЦикла;                                      
   
   Если Лев(Стр2,1)<>"*" Тогда      
       Если Лев(Ст1,СтрДлина(СпЗ[1])) <> СпЗ[1] Тогда
           Возврат(0)
       КонецЕсли;
   КонецЕсли;        
   Если Прав(Стр2,1)<>"*" Тогда      
       Если Прав(Ст1,СтрДлина(СпЗ[n])) <> СпЗ[n] Тогда
           Возврат(0)
       КонецЕсли;
   КонецЕсли;  
   
   Для k = 1 По n Цикл  
       m =  Найти(Ст1,СпЗ[k]);
       Если m>0 Тогда
           Ст1 = Прав(Ст1,СтрДлина(Ст1)-m+1-СтрДлина(СпЗ[k]));
       Иначе
           Возврат(0);
       КонецЕсли;
   КонецЦикла;
   
   Возврат(1);
   
КонецФункции //НайтиПоШаблону()