RU/2: Форум. Общение пользователей и разработчиков OS/2 (eCS). : Разбиение строки на подстроки


Список сообщений | Написать новое | Ответить на сообщение | Домой Поиск:
Предыдущее сообщение | Следующее сообщение
From : Improver
To : Aleksey Tarasow
Subj : Разбиение строки на подстроки

> > > Хочу спросить совета у гуру.
> > > В подпрограмму передается одна строка (единая строка) в которой может содержаться (или нет) несколько подстрок разделенных запятой. Это все, что знаем о строке. Теперь мне нужно разбить строку на подстроки.
> > > Пример строки: DateDo="01.01.2011", DateEnd="25.02.2013", ListCode='Pump1 Pump2', Text="220V ON"
> > > Тут все просто, но что делать если "запятая" окажется внутри подстроки?
> > > Пример строки: DateDo="01.01.2011", DateEnd="25.02.2013", ListCode='Pump1 Pump2', Text="Что-то не так, как надо"
> > > Для этого случая принят алгоритм: находим запятую, если до неё в строке четное количество кавычек, считаем запятая ограничивает подстроку, если нечетно, считаем запятая внутри подстроки.
> > > Опять же работало до момента пока не появилась такая строка: wordpos("tae",User)>0
> > > Тут вступают в силу ещё и скобки...
> > > Сейчас ломаю голову над более менее универсальным алгоритмом разбора строки. Повторим вводные:
> > > 1. Разделитель подстрок "запятая".
> > > 2. Возможно наличие как минимум следующих ограничителей: "одинарная кавычка", "двойная кавычка", "обратная кавычка", "(", ")", "{", "}"
> > > 3. Внутри подстроки есть вероятность встречи ограничителей в любом в любом порядке и без порядке. Например, в качестве куска текста выдернутого из контекста.
> > >
> > > Кто подскажет алгоритм для Rexx?
> >
> > Разбиваешь исходную строку при помощи parse value на N подстрок по разделителю "запятая", потом проверяешь количество кавычек, скобок и т.д. в первой подстроке, если оно нечётное, то соединяешь со следующей строкой, и так далее по-порядку обрабатываешь все подстроки...
>
> Так и делаю в настоящий момент, но условий становиться слишком много, и боюсь со временем их число будет только расти. Что сильно усложнит логику.
> По этому ищу альтернативные пути решения. В настоящий момент написал скрипт просматривающий строку по символьно. Вот что получились. Все текущие задачи решает, да же есть не большой запас на развитие. Но смущает то, что тратим время на каждый символ.
>
> =====
> SubSpace=d2c(01) /* Код для замены пробела */
> SubDoubleQuotes=d2c(02) /* Код для замены двойных кавычек */
> /*call value Where,"'wordpos('tae',User)>0'"*/
>
> call value Where,'DateDo="01,01,2011", DateEnd="25.02.2013", ListCode='Pump1 Pump2', Text="220V ON"'
>
>
> ActiveQuotes='' /* Активный тип кавычек, устанавливается при первом использовании */
> OpenQuotes=0 /* Количество открытых кавычек */
> OpenBracket=0 /* Количество открытых скобок */
> rcWhere=''
> WhereNew=''
> do n=1 to length(Where)
> parse value Where with sym 2 Where
> select
> when sym==ActiveQuotes then do
> OpenQuotes=OpenQuotes+1
> end
> when sym=="'" then do
> ActiveQuotes=sym
> OpenQuotes=OpenQuotes+1
> end
> when sym=='"' then do
> ActiveQuotes=sym
> OpenQuotes=OpenQuotes+1
> end
> when sym=="(" then OpenBracket=OpenBracket+1
> when sym==")" then OpenBracket=OpenBracket-1
> when sym==',' then do
> if OpenBracket=0 then
> if OpenQuotes//2=0 then do
> WhereNew=WhereNew' 'translate(strip(rcWhere),SubSpace,' ') /* Заменяем пробелы в условии на код заменитель и добавляем в конец строки команды */
> ActiveQuotes='' /* Обнулили Активные кавычки, для того что в следующем блоку можно были использовать кавычки другого типа. */
> OpenQuotes=0
> rcWhere=''
> sym=''
> end /* if */
> end
> Otherwise nop
> end /* select */
> rcWhere=rcWhere||sym
> end n
> WhereNew=WhereNew' 'translate(strip(rcWhere),SubSpace,' ') /* Добавляем остаток строки, который не удалось отработать в цикле. */
> ====
В принципе, можно и так, хотя я предлагал сначала побить строку по запятым на подстроки, а потом их анализировать... Непонятно мне в твоём алгоритме, зачем заменять пробелы и двойные кавычки символами с кодами 01 и 02, это требуется для дальнейшей обработки?

И ещё такая фишка: совсем не обязательно строку разбирать посимвольно, можно воспользоваться функцией verify(Where, '()"{}[]'||"'", 'M') и получить первую позицию символа из списка (второй аргумент), это позволит пропустить анализ символов строки до этой позиции. Вот небольшой пример её использования:
=======
p = 0
do until p = 0
p = verify(Where, ',()"{}[]'||"'", 'M', p + 1)
if p > 0 then say p
end
=======
Тут в цикле будут выведены все номера позиций встретившихся в строке символов: , ( ) " { } [ ] '
Потом, при необходимости, достаточно просто будет дополнять в поиск и другие символы.

Wed 28 Jan 2015 21:45 Mozilla/5.0 (OS/2; Warp 4.5; rv:17.0) Gecko/20100101 Firefox




Programmed by Dmitri Maximovich, Dmitry I. Platonoff, Eugen Kuleshov.
25.09.99 (c) 1999, RU/2. All rights reserved.
Rewritten by Dmitry Ban. All rights ignored.