Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Oracle Новый топик    Ответить
 парсер строки следующего вида  [new]
Adtain
Member

Откуда: Moscow
Сообщений: 290
Все привет! Помогите пожалуйста, что-то не могу уже сообразить.

Есть строка, вида:

"and[счет1;and|счет2;and|!счет3]or|счет4;and|!счет5..."

Что разворачивается в запрос вида:

and (   счет1 like ...
    and счет2 like ...
    and счет3 not like ...
    )
 or счет4 like ...
and счет5 not like ...

Если обозвать эту строчку cl и не использовать квадратные скобки (которые транслируются в обычные, для объединения условий), то выглядит все более менее:

for p in 1..length(cl) - length(replace(cl, ';', '')) loop
  sSQL := sSQL || '                  '
               || strtok(strtok(cl, ';', p), '|', 1)
	       || ' '
	       || (case when strtok(cl, ';', p) like 'з' then 'db.acc_number' else 'substr(db.acc_number, 19, 5)' end)
	       || ' '
	       || (case when substr(strtok(strtok(cl, ';', p), '|', 2), 1, 1) = '!'
		        then 'not like ''%' || substr(strtok(strtok(cl, ';', p), '|', 2), 2) || '%'' '
		        else 'like ''%' || strtok(strtok(cl, ';', p), '|', 2) || '%'' '
	            end)
	       || CR;						 
end loop;

Но вот со скобками сообразить не могу. Была идея сначала отрезать кусок перед первой [ открывающейся скобкой и его обработать, потом обработать то что в скобках и конец соответственно, НО тут может быть структура совершенно иная нежели я привел выше, допустим ... [...] ... [...] ... тогда получается что внутри уже обычное условие без скобок.
28 июн 11, 01:31    [10884425]     Ответить | Цитировать Сообщить модератору
 Re: парсер строки следующего вида  [new]
wildwind
Member

Откуда: Москва
Сообщений: 1296
Adtain,

Я бы вместо substr взял за основу regexp_replace.
28 июн 11, 03:28    [10884483]     Ответить | Цитировать Сообщить модератору
 Re: парсер строки следующего вида  [new]
Adtain
Member

Откуда: Moscow
Сообщений: 290
Проблема что это будет ещё использоваться и на Оракле 9, а там вроде нету такой функции.
28 июн 11, 10:38    [10885071]     Ответить | Цитировать Сообщить модератору
 Re: парсер строки следующего вида  [new]
Репозиторий суппозиториев
Guest
а там вроде нету такой функции.

А функция strtok там, видимо, есть?
28 июн 11, 11:05    [10885266]     Ответить | Цитировать Сообщить модератору
 Re: парсер строки следующего вида  [new]
Adtain
Member

Откуда: Moscow
Сообщений: 290
Есть. Я ж там тестирую.
28 июн 11, 11:16    [10885367]     Ответить | Цитировать Сообщить модератору
 Re: парсер строки следующего вида  [new]
Alexander Konakov
Member

Откуда:
Сообщений: 1027
Adtain
Есть. Я ж там тестирую.

Чудеса...
28 июн 11, 11:26    [10885462]     Ответить | Цитировать Сообщить модератору
 Re: парсер строки следующего вида  [new]
Adtain
Member

Откуда: Moscow
Сообщений: 290
Ага, спасибо.
28 июн 11, 11:44    [10885606]     Ответить | Цитировать Сообщить модератору
 Re: парсер строки следующего вида  [new]
andreymx
Member

Откуда: Запорожье
Сообщений: 54398
Adtain
for p in 1..length(cl) - length(replace(cl, ';', '')) loop
  sSQL := sSQL || '                  '
               || strtok(strtok(cl, ';', p), '|', 1)
	       || ' '
	       || (case when strtok(cl, ';', p) like 'з' then 'db.acc_number' else 'substr(db.acc_number, 19, 5)' end)
	       || ' '
	       || (case when substr(strtok(strtok(cl, ';', p), '|', 2), 1, 1) = '!'
		        then 'not like ''%' || substr(strtok(strtok(cl, ';', p), '|', 2), 2) || '%'' '
		        else 'like ''%' || strtok(strtok(cl, ';', p), '|', 2) || '%'' '
	            end)
	       || CR;						 
end loop;
скажу не по сути вопроса, а по дизайну процедуры:
сюда аж свистит переменная:
  v_token := strtok(cl, ';', p);
28 июн 11, 11:54    [10885661]     Ответить | Цитировать Сообщить модератору
 Re: парсер строки следующего вида  [new]
andreymx
Member

Откуда: Запорожье
Сообщений: 54398
Adtain

если я не ошибаюсь, то, судя по куску
for p in 1..length(cl) - length(replace(cl, ';', '')) loop
, у тебя количество слов равняется количеству точек с запятой,

в этом случае
and|!счет3]or|счет4
- это одно слово для разбора
?
28 июн 11, 13:01    [10886082]     Ответить | Цитировать Сообщить модератору
 Re: парсер строки следующего вида  [new]
andreymx
Member

Откуда: Запорожье
Сообщений: 54398
преобразовать строку
'and[счет1;and|счет2;and|!счет3]or|счет4;and|!счет5...'
в строку
and ( счет1 and счет2 and !счет3 ) or счет4 and !счет5
с помощью простой замены
REPLACE(REPLACE(REPLACE(REPLACE(t, '[', ' ( '), ']', ' ) '), ';', ' '), '|', ' ')
а затем парсить в ней отдельные слова - например, под маску типа "!" + "счет" + "цифра", не меняя остального
28 июн 11, 13:10    [10886146]     Ответить | Цитировать Сообщить модератору
 Re: парсер строки следующего вида  [new]
Adtain
Member

Откуда: Moscow
Сообщений: 290
Спасибо! Попробую.
Пока сделал два цикла отдельно по кускам в скобках и отдельно по всему остальному.
28 июн 11, 17:49    [10888523]     Ответить | Цитировать Сообщить модератору
 Re: парсер строки следующего вида  [new]
andreymx
Member

Откуда: Запорожье
Сообщений: 54398
Adtain
Спасибо! Попробую.
Пока сделал два цикла отдельно по кускам в скобках и отдельно по всему остальному.
где гарантия, что не будет вложенных скобок? тут рекурсия нужна
28 июн 11, 21:03    [10889246]     Ответить | Цитировать Сообщить модератору
 Re: парсер строки следующего вида  [new]
Adtain
Member

Откуда: Moscow
Сообщений: 290
Да, это я понял. Спасибо ещё раз.
30 июн 11, 12:12    [10898370]     Ответить | Цитировать Сообщить модератору
 Re: парсер строки следующего вида  [new]
Евгений Переверзев
Member

Откуда: Благовещенск
Сообщений: 13
andreymx,
REPLACE(REPLACE(REPLACE(REPLACE(t, '[', ' ( '), ']', ' ) '), ';', ' '), '|', ' ')
меняем на
TRANSLATE (t, '[;|]', '(  )')
30 июн 11, 14:03    [10899479]     Ответить | Цитировать Сообщить модератору
Все форумы / Oracle Ответить