Russian Qt Forum

Qt => Общие вопросы => Тема начата: RomiX от Июнь 27, 2012, 08:30



Название: Парсинг строк
Отправлено: RomiX от Июнь 27, 2012, 08:30
Здравствуйте, нужна помощь с разбором на составляющие следующих строк
1)1,2,3,{4,5,6},7,8,9,"что угодно, {}'..."
на выходе нужно получить 1 2 3 {4,5,6} 7 8 9 "что угодно, {}'..."
если просто сделать split строки по запятой, то разбивается и последовательности в скобках, что не верно

2) ab.cd.ef(123, 1.12, "что угодно (строка)", 4)
тут практически та же проблема, если в скобках в строке не будет символов ( или ) то всё прекрасно работает если разбить строку по этим самым символам, но в строке может быть любой из этих символов, и тогда уже всё работает не так...
Посоветуйте что нибудь, а то в голову лезет совсем мудреные способы, заранее спасибо.


Название: Re: Парсинг строк
Отправлено: lighting от Июнь 27, 2012, 09:00
собственно в вопросе кроется ответ - QRegexp.


Название: Re: Парсинг строк
Отправлено: RomiX от Июнь 27, 2012, 09:06
можно по-подробней пожалуйста? я ни как не могу основательно разобраться в регулярных выражениях((( простые могу написать а более сложные - нет


Название: Re: Парсинг строк
Отправлено: Syveren от Июнь 27, 2012, 09:27
Код
C++ (Qt)
  QString str="1,2,3,{4,5,6},7,8,9";
    int pos = 0;
    QRegExp rx("([^,]|\\{.*\\})"); // Ищем символ не равный запятой или выражение в скобках
 
    while((pos = str.indexOf(rx,pos))>=0)
    {
        pos+=rx.cap(0).length();
       qDebug()<<rx.cap(0);
    }
 
out::
"1"
"2"
"3"
"{4,5,6}"
"7"
"8"
"9"
Остальное по аналогии 8)


Название: Re: Парсинг строк
Отправлено: RomiX от Июнь 27, 2012, 09:30
большое спасибо :)


Название: Re: Парсинг строк
Отправлено: trot от Июнь 27, 2012, 10:00
Попробуй так

Код:
QString t = "1,2,3,{4,5,6},7,8,9";
t.replace(QRegExp(",|(\\{([^,],)*[^,]\\})"), " \\1");


Название: Re: Парсинг строк
Отправлено: RomiX от Июнь 28, 2012, 10:30
не совсем то, это просто удаляет запятые, но мне то нужно выделить кусочки строки, при чём то что в скобках не должно разбиваться
я дошёл до такого:
Код:
QString str = "127, 123.123, 'hey', {1, 2, 3, 4}, {1.122, 1.2121, 1.111}, {1, 2, 3}";
int pos = 0;
QRegExp rx("([^, ]+|[\\\"'].*[\\\"'])|\\{.*\\}");
while((pos = str.indexOf(rx,pos))>=0)
{
    pos+=rx.cap(0).length();
    qDebug()<<rx.cap(0);
}

вывод
"127"
"123.123"
"'hey'"
"{1, 2, 3, 4}, {1.122, 1.2121, 1.111}, {1, 2, 3}"
что не верно((


Название: Re: Парсинг строк
Отправлено: RomiX от Июнь 28, 2012, 10:43
вроде получилось:
([^, ]+|[\\\"'][^'\\\"]*[\\\"']|\\{[^{}]*\\})
надеюсь опять не вылезет багов...

нет(
на такой строке 123, {'string', '}'}, 123
выдаёт
"123"
"{'string', '}"
"'}"
"123"

а если сделать что в скобках {} могут быть любые символы, то тогда объединяются несколько подряд идущих скобок, типа этого {1, 2, 3}, {1, 2, 3}, {1,2,3} и тд
т.е. нужно сделать что в скобках {} могут быть любые символы кроме самих скобок, НО если встречаются кавычки, то в них может быть вообще что угодно, но как можно это сделать?


Название: Re: Парсинг строк
Отправлено: Syveren от Июнь 28, 2012, 12:15
 QRegExp rx("([^, ]+|\\{([^{}]*|'([^{}]*|.*)')\\})");


Название: Re: Парсинг строк
Отправлено: RomiX от Июнь 28, 2012, 12:40
почти) но не совсем...
на 127, 123.123, \"hey!!!\",  {1, 2,   3    , 4, 5}, {1.12, 1.13, 2.123}, {    '}{([str1])}'     ,   'str2'  , 'str3'}

выдаёт
"127"
"123.123"
""hey!!!""
"{1, 2,   3    , 4, 5}"
"{1.12, 1.13, 2.123}"
"{    '}"
"{([str1])}'"
"'str2'"
"'str3'}"

т.е. он зажёвывает скобку из кавычек, чего не должен делать


Название: Re: Парсинг строк
Отправлено: trot от Июнь 28, 2012, 13:33
Цитировать
НО если встречаются кавычки, то в них может быть вообще что угодно, но как можно это сделать?

Одним регулярным выражением это сделать довольно сложно. Само выражение получится очень тяжелым. Предлагается разбить задачу на части.
Сначало найти все вложенные строки, их вырезать и запомнить, вместо них подставить какую-то свою индексируемую литералу. Далее рабтать со строкой уже не имеющую вложенных строк. После обработки вставить вместо литерал вырезанные подстроки.


Название: Re: Парсинг строк
Отправлено: Syveren от Июнь 28, 2012, 13:43
QRegExp rx("([^, ]+|\\{([^{}]*)\\}|\\{[^{}]*'.*'[^{}]*\\})");
Только через полгода без бутылки не разберёшся, что имелось ввиду)
А вообще, если важно быстродейсвие лучше свой парсер написать - анализирвоать посимвольно


Название: Re: Парсинг строк
Отправлено: RomiX от Июнь 28, 2012, 13:59
есть! спасибо)
бешенная производительность не нужна, разбор будет выполняться не очень часто...


Название: Re: Парсинг строк
Отправлено: trot от Июнь 28, 2012, 14:13
127, 123.123, \"hey!!!\",  {1, 2,   3 , ',,,ddd,,'   , 4, 5}, {1.12, 1.13, 2.123}, {    '}{([str1])}'     ,   'str2'  , 'str3'}

Интересно как обработается эта строка? А вообще, чтобы написать регулярное выражение надо четко понимать что надо иметь на выходе. Вы же пока четко не сформулировали свои требования.


Название: Re: Парсинг строк
Отправлено: RomiX от Июнь 28, 2012, 14:21
выдает
"127"
"123.123"
""hey!!!""
"{1, 2,   3 , ',,,ddd,,'   , 4, 5}, {1.12, 1.13, 2.123}, {    '}{([str1])}'     ,   'str2'  , 'str3'}"

это аргументы для какой-либо функции, нужна поддержка целых, дробных типов, строк, массивов целых, дробных и строк. соответственно на выходе нужно всё это получить по отдельности, в данном случае
"127"
"123.123"
""hey!!!""
"{1, 2,   3 , ',,,ddd,,'   , 4, 5}
"{1.12, 1.13, 2.123}
"{    '}{([str1])}'     ,   'str2'  , 'str3'}"
дальше уже все работает как надо, алгоритму известно какие данные ждать и он обрабатывает их как положено

то что будет ',,,ddd,,' мало вероятно, разве что по ошибке, т.к. это целочисленный массив


Название: Re: Парсинг строк
Отправлено: Igors от Июнь 28, 2012, 14:50
А вообще, если важно быстродейсвие лучше свой парсер написать - анализирвоать посимвольно
И не только быстродействие - мне писать самому всегда было интереснее чем заучивать чужие классы (часто мудаковатые).