Имя: Пароль:
IT
 
Регулярное выражение. Прошу помощи
,
0 oleg_km
 
09.01.12
12:43
Нужна конкретная помощь. Мало практики, никак не могу понять.

Есть строка:
realm="1C-AGP", qop="auth,auth-int", nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", opaque="5ccc069c403ebaf9f0171e9517f40e41", algorithm=MD5, stale=false

Нужно превратить в массив, в соответствии с запятыми, но игнорировать запятые, экранированные кавычками. Решал аналогичную проблему, но не смог и обошел, сейчас не могу обойти.
1 Kreont
 
09.01.12
12:43
2 oleg_km
 
09.01.12
12:50
(1)

Спасибо, но не глубоко вникая в твой код не смог понять, как он будет игнорировать запятые в кавычках.

Мне нужен такой результат:
realm="1C-AGP"
qop="auth,auth-int"
nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093"
opaque="5ccc069c403ebaf9f0171e9517f40e41"
algorithm=MD5
stale=false

А у тебя получится:
realm="1C-AGP"
qop="auth                 <--------   улавливаешь разницу
auth-int"
nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093"
opaque="5ccc069c403ebaf9f0171e9517f40e41"
algorithm=MD5
stale=false
3 Kreont
 
09.01.12
12:54
А ну да тут ведь csv не по стандарту:(
Хотя замени сначала в исх.строке:
", " на "#@%BLA!" и используй как разделитель
4 KUBIK
 
09.01.12
12:57
замени запятую на символ, которого заведомо никогда не должно быть в твоих значениях, обработай csv, затем обратно.
5 oleg_km
 
09.01.12
12:58
(3)

Извини, Василий, но опять мимо. Есть запятая, которая находится в тексте внутри кавычек: ="auth,auth-int". Она то и не является разделетелем. То есть разделители, это только запятые вне закавыченного текста. Это задачка как раз для регулярных выражений, но я пока в них не могу въехать
6 Живой Ископаемый
 
09.01.12
13:01
Дополнение:
функция, которая правильно раскладывает строки типа вида:
20100912; 17.19;"Назначение платежа; которое не нужно делить на подстроки"
То есть на три подстроки а не четыре:


 
RegExp = Новый COMОбъект("VBScript.RegExp");
   Результат = Новый Массив();
   
   RegExp.IgnoreCase = Ложь; //Игнорировать регистр
   RegExp.Global = Истина; //Поиск всех вхождений шаблона
   RegExp.MultiLine = Ложь; //Многострочный режим
   
   RegExp.Pattern = "(?:^|;)(\""(?:[^\""]+|\""\"")*\""|[^;]*)"; //вот наш супер шаблон
   //RegExp.Pattern = ";|;|;|;|;;|;|;|;|;|;|;|;|;;|;|;"; //вот наш супер шаблон
   Matches=RegExp.Execute(Стр);
   ЧислоВхождений=Matches.Count();
   //Сообщить(Стр,СтатусСообщения.Важное);
   Если ЧислоВхождений>0 Тогда
       Для к = 0 По ЧислоВхождений-1 Цикл
           Match = Matches.Item(к);
           
           SubMatches = Match.SubMatches;
           ЧислоПодвыражений=SubMatches.Count();
           Для н = 0 По ЧислоПодвыражений-1 Цикл
               SubMatch=SubMatches.Item(н);
               Если SubMatch="" Тогда
                   //Продолжить;
               КонецЕсли;    
               Результат.Добавить(SubMatch);
               //Сообщить("Подстрока: "+SubMatch);
           КонецЦикла;    
       КонецЦикла;
   Иначе
       //Сообщить("Вхождений шаблона не найдено");
   КонецЕсли;
   Возврат Результат;
7 Kreont
 
09.01.12
13:01
(5) см. (4)+(3)
П.С. У меня в (3) текст такой: "запятаяпробел" = ", "
8 Живой Ископаемый
 
09.01.12
13:02
только вот тут:
RegExp.Pattern = "(?:^|;)(\""(?:[^\""]+|\""\"")*\""|[^;]*)"; //вот наш супер шаблон
вместо точек с запятой - запятая
9 aleks-id
 
09.01.12
13:07
массивстрок = стрзаменить(realm,", ",символы.пс);
10 Живой Ископаемый
 
09.01.12
13:09
2(9) ты ведь прочитал (2), верно?
11 aleks-id
 
09.01.12
13:11
(10) а ты ведь внимательно посмотрел, что у него разделитель строк - запятая плюс пробел да?
12 Живой Ископаемый
 
09.01.12
13:12
2(11) это частность - у него в строке может быть запятая и пробел и все...
13 Живой Ископаемый
 
09.01.12
13:12
realm="1C-AGP", qop="auth, auth-int"
14 aleks-id
 
09.01.12
13:12
(12) давай не будем за него телепатить ок? ;)
15 Живой Ископаемый
 
09.01.12
13:15
2(14) давай.. может конечно ты и прав, но тогда твой вариант предполагает что автор идиот, который проглядел такой простой вариант.. я так с людьми не могу, уж извини... предпочитаю думать что он просто привел не самый характерный пример строки, но объяснил именно то что ему нужно, а это решается простым паттерном из (8)
16 oleg_km
 
09.01.12
13:16
(14)

Нечего телепатить, все написано. "Живой Ископаемый" все правильно понял.

(8)

Твой пример с ; работает, заменяю на , - не хочет. Может , какой-то спецсимвол в RegExp'ах
17 aleks-id
 
09.01.12
13:16
+(14) и даже если это так - все сводится к 3 строчкам:
массивстрок = стрзаменить(НашаСтрока,""",","@@##$$");
массивстрок = стрзаменить(массивстрок,",",символы.пс);
массивстрок = стрзаменить(массивстрок,"@@##$$",""",");
18 Живой Ископаемый
 
09.01.12
13:18
2(16) тогда фигово... я не большой знаток регэкспа.. но то что помню - когда я его нашел, он изначально был для запятой...
19 aleks-id
 
09.01.12
13:19
тьфу. неправильно в (17)
20 Живой Ископаемый
 
09.01.12
13:19
21 Живой Ископаемый
 
09.01.12
13:20
"^(("(?:[^"]|"")*"|[^,]*)(,("(?:[^"]|"")*"|[^,]*))*)$"
"(?:^|,)(\\\"(?:[^\\\"]+|\\\"\\\")*\\\"|[^,]*)"
22 Kreont
 
09.01.12
13:20
(2) Я так понял не проверял готовой обработкой даже из (1)?
У меня для данной строки все сработало нормально. проверь.
23 Живой Ископаемый
 
09.01.12
13:21
24 Живой Ископаемый
 
09.01.12
13:22
но только кавычки внутри нужно удвоить
25 oleg_km
 
09.01.12
13:27
(20)
Не работает вообще, там товарищ внизу написал:
Couldn't get this to work in .net :(

(23)
Почему-то ненужный разделитель все равно использует. Буду рыть дальше. Спасибо за участие
26 Живой Ископаемый
 
09.01.12
13:28
потом только опубликуй годный шаблон как найдешь. :)
27 Steel_Wheel
 
09.01.12
13:35
(0) Эта штука может помочь: много шаблонов готовых

http://gskinner.com/RegExr/
28 oleg_km
 
09.01.12
13:39
(26)

Твой вариант тоже не работает, если исходную строку изменить на:

20100912; 17.19; Что-то "Назначение платежа; которое не нужно делить на подстроки"

Так что это не совсем CSV
29 Живой Ископаемый
 
09.01.12
13:48
2(28) стопроцентов работает.. сейчас
30 oleg_km
 
09.01.12
13:54
(29)

Только что пробовал, бъет внутри кавычек тоже
31 oleg_km
 
09.01.12
13:58
Пока универсального шаблона опять не получилось. Получился более менее подходящий для данной задачи:

([a-z]*)=(?:([\'"])([^\2]+?)\2|([^\s,]+)) - взято из исходников PHP
32 Живой Ископаемый
 
09.01.12
14:00
33 oleg_km
 
09.01.12
14:03
(32)

между ; и " вставь символы, на моей строке попробуй:

20100912; 17.19; Что-то "Назначение платежа; которое не нужно делить на подстроки"
34 Живой Ископаемый
 
09.01.12
14:05
а понятно
35 del123
 
15.01.12
13:09
А чем плох такой код?)



   Ковычка = ложь;
   ТекСтр = Стр;
   ТекПодстрока = "";
   Список = новый СписокЗначений;
   Поз2 = 0;
   пока истина цикл
       если ковычка тогда
           ТемпСтр = Лев(ТекСтр, поз2);
           ТекСтр = Сред(ТекСтр, поз2 + 1, СтрДлина(ТекСтр));
           Поз2 = найти(ТекСтр, """");
           ТемпСтр = ТемпСТр + Лев(ТекСтр, Поз2);
           ТекСтр = Сред(ТекСтр, поз2 + 1, СтрДлина(ТекСтр));
           Список.Добавить(СокрЛП(ТемпСтр));
           Ковычка = ложь;
       иначе
           Поз1 = Найти(ТекСтр, ",");
           Поз2 = Найти(ТекСтр, """");
           если поз1 = 0 тогда
               список.Добавить(СокрЛП(ТекСтр));
               прервать;
           иначеесли поз1 = 1 тогда
               ТекСтр = Сред(ТекСтр, 2, СтрДлина(ТекСтр));
           иначеесли Поз2 = 0 или (поз1 < поз2) тогда
               Список.Добавить(СокрЛП(Лев(ТекСтр, Поз1 - 1)));
               ТекСтр = Сред(ТекСтр, поз1 + 1, СтрДлина(ТекСтр));
           иначе
               Ковычка = истина;
           конецесли;
       конецесли;
   конеццикла;
   Список.ВыбратьЭлемент();
36 Torquader
 
15.01.12
14:08
Ну - запятую в попу, а потом обычным парсером для командной строки - разобъёт на составляющие, а уже в них отрезать запятую с конца (если она там есть), а также разделить по знаку равно на переменную и её значение.
37 Живой Ископаемый
 
15.01.12
17:41
2(35) если работает, то всем хорош... Вообще код на чистом языке 1С предпочтительней, потому как не будет зависеть от среды исполнения - серверная она или клиентская, толстый или тонкий клиент, винда или линукс, какие права у пользователя под которым исполняется экземпляр программы и тому подобное...

Просто иногда почему-то интересно.
38 oleg_km
 
15.01.12
20:12
(37) Разбор строки чистым кодом ну уровне сложных регулярных выражений - это практически всегда посимвольный разбор строки. А это средствами 1С очень медленно. Я сравнивал функцию-инициализатор строки (просто создает строку символов заданной длины) реализация на 1С уступает реализации на C++ в 1000 раз. А если нужно обработать текствый файл мегабайты? Просто хотелось одолеть китайскую грамоту регулярных выражений, все таки получается код всего четыре строчки, а не целый экран. Ладно, как-нибудь освоим
39 Живой Ископаемый
 
15.01.12
20:14
2(38) ну да, если ты уверен в каких условиях будет выполняться код и нужно чтобы он исполнялся быстро, тогда любые средства хороши...
40 Simod
 
16.01.12
07:29
Как-то так:

т_Текст        = СоздатьОбъект("Текст");
сз_Список    = СоздатьОбъект("СписокЗначений");
п_РС        = РазделительСтрок;

т_Текст.Открыть("C:\test.txt");    // файл со стороками

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

сз_Список.ВыбратьЗначение(,,,, 0);