pcre задрал)

Тема в разделе "WASM.BEGINNERS", создана пользователем loginrl_103, 3 май 2008.

  1. loginrl_103

    loginrl_103 New Member

    Публикаций:
    0
    Регистрация:
    8 фев 2008
    Сообщения:
    271
    запарился с pcre.

    всё началось с того что мне надо обычную строку разбить по словам. шаблон задаю самый обычный "\\s*". Строка "ababa q.1 w.2": то есть должно найтись 3 совпадения...но хрена чего он находит.код C++
    Код (Text):
    1.         ...
    2. int parse_str (char *str)
    3. pcre *hpe;
    4. const char *error, *buf;
    5. int erroroffset, i = 0, j = 0;
    6. int ovector[300], wsp[300], count = 0;
    7. if (!(hpe = pcre_compile ("\\s*", PCRE_CASELESS|PCRE_MULTILINE, &error, &erroroffset, NULL)))
    8.    return -1;
    9. pcre_extra *f_ext=pcre_study (hpe, 0, &error);
    10. count = pcre_exec (hpe, f_ext, str, strlen(str), 0, 0, ovector, 300);
    11. ...
    на выходе count=1 что не соотвествует истине (

    решил было подключить pcrecpp но тут же посыпались ошибки из-за Code Generation -> Runtime Library: собирал и проект и pcre как /MDd и как /MTdкод C++

    Код (Text):
    1. msvcprtd.lib(MSVCP80D.dll) : error LNK2005: "public: __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::~basic_string<char,struct std::char_traits<char>,class std::allocator<char> >(void)" (??1?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ) already defined in pcrecpp.lib(pcrecpp.obj)
    2. msvcprtd.lib(MSVCP80D.dll) : error LNK2005: "public: __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >(char const *)" (??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@PBD@Z) already defined in pcrecpp.lib(pcrecpp.obj)
    3. pcrecpp.lib(pcrecpp.obj) : error LNK2019: unresolved external symbol __invalid_parameter_noinfo referenced in function "public: int __thiscall std::_String_const_iterator<char,struct std::char_traits<char>,class std::allocator<char> >::operator-(class std::_String_const_iterator<char,struct std::char_traits<char>,class std::allocator<char> > const &)const " (??G?$_String_const_iterator@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QBEHABV01@@Z)
    pcrecpp мне не принципиален, но не могу одолеть почему шаблон в сишном pcre не хочет работать...
    кто сталкивался с этими проблемами или есть какие то идеи по её решению - помогите.

    ps. всё что нашёл в поиске - игра с /MDd и перекомпиляцией проектов с одинаковыми опциями... не помогло.
     
  2. dag

    dag New Member

    Публикаций:
    0
    Регистрация:
    17 авг 2004
    Сообщения:
    446
    тебе больше подойдёт /\w+/ig , а совсем подойдёт /[a-zA-Z\.0-9]+/ig или /\s+/ig смотря что ты хотел сказать в /\s*/ig
    А вообще man perlretut или man perlrequick + у pcre есть утиль pcretest =)
     
  3. loginrl_103

    loginrl_103 New Member

    Публикаций:
    0
    Регистрация:
    8 фев 2008
    Сообщения:
    271
    в perl то проблем нету) проблемы только в сях ( при имитации опций ig вапще больше ничего не находится...странный этот сишный pcre)
     
  4. dag

    dag New Member

    Публикаций:
    0
    Регистрация:
    17 авг 2004
    Сообщения:
    446
    Код (Text):
    1. \usr\local\bin> pcretest
    2. PCRE version 7.4 2007-09-21
    3.  
    4.   re> /\s*/ig
    5. data> ababa q.1 w.2
    6.  0:
    7.  0:
    8.  0:
    9.  0:
    10.  0:
    11.  0:
    12.  0:
    13.  0:
    14.  0:
    15.  0:
    16.  0:
    17.  0:
    18.  0:
    19.  0:
    20. data>
    21.   re> /\w+/ig
    22. data> ababa q.1 w.2
    23.  0: ababa
    24.  0: q
    25.  0: 1
    26.  0: w
    27.  0: 2
    28. data>
    29.   re> /[a-zA-Z\.0-9]+/ig
    30. data> ababa q.1 w.2
    31.  0: ababa
    32.  0: q.1
    33.  0: w.2
    34. data>
    35.   re> /\s+/ig
    36. data> ababa q.1 w.2
    37.   0:
    38.   0:
    39. data>^C
    исходники pcretest поставляются вместе с pcre, если нужны могу приатачить
     
  5. _basmp_

    _basmp_ New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2005
    Сообщения:
    2.939
    шаблон \s* определяет 0 или больше [ \t\r\n]. В вашем случае лучше \s+ (только-что проверил и \s* и \s+ выдают одинаковые и правильные результаты)
     
  6. dag

    dag New Member

    Публикаций:
    0
    Регистрация:
    17 авг 2004
    Сообщения:
    446
    \s = [\ \t\r\n\f] => \s* = \s от 0 до oo => грубо говоря получим позиции всех символов +1 включая \f

    pcre_exec возвращает не количество, а смещение в строке найденой подстроки согласно шаблону ( It returns offsets to captured substrings) поэтому возвращаетcя 1
     
  7. _basmp_

    _basmp_ New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2005
    Сообщения:
    2.939
    dag
    Ну? А я не то-же сказал?
     
  8. dag

    dag New Member

    Публикаций:
    0
    Регистрация:
    17 авг 2004
    Сообщения:
    446
    нет. \s* и \s+ вернут разные результаты
    loginrl_103
    не слушай нас посмотри реализацию в pcredemo и pcretest (по твоему коду я так понял ты хотишь получить позиции "пробелов", а не список "слов" - "q.1" и "w.2" ты IMHO тоже считаешь словами)
     
  9. ring4

    ring4 New Member

    Публикаций:
    0
    Регистрация:
    19 ноя 2006
    Сообщения:
    279
    loginrl_103
    епанутся (простите не удержался) судя по тому что вам надо, не легче строку разбить по словам таким способом:?
    Код (Text):
    1. void split(const string& s, char c, vector<string>& V)
    2. {
    3. string::size_type i=0;
    4. string::size_type j=s.find(c)
    5.  
    6. while(j != string::npos){
    7. v.push_back(s.substr(i,j-1));
    8. i=++j;
    9. j=s.find(c, j);
    10.  
    11. if(j==string::npos)
    12. v.push_back(s.substr(i, s.length()));
    13. }
    14. }
    вызов осуществляется
    split(str,' ', vec);
    str - sting
    vec- vector

    PS. толи я дурак толи лыжи не едут, но смотря на ваш код мне становится страшно, что вы с ним хотите я не представляю, обясните если не трудно.
    ЗЫЫ. код не проверял, лень компилятор запускать. вроде правильно, если не забыл где скобку или запятую
     
  10. _basmp_

    _basmp_ New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2005
    Сообщения:
    2.939
    dag
    проверил еще раз. в строке "fgh jkt 2324 .we.r.4. uigh kj", по крайней мере, шаблоны \s* и \s+ дают одинаковые результаты.

    ring4
    Да наверно и еще проще можно. Особенно если от C++ отказаться. Например
    Код (Text):
    1. int StrSpaceSplit(char* str,char** sarr){ //предположим, что массив sarr достаточно длинен
    2.   char c, cold;
    3.   char* ps;
    4.   char** psa;
    5.   if((!str) || (!sarr)) return 0;
    6.   for(ps=str, cold=0, psa=sarr ; c=*ps; cold=c, ps++)
    7.     if(c==' ' || c=='\t' || c=='\r' || c=='\n')
    8.       *ps=c=0;
    9.     else if(!cold) {
    10.       *psa=ps;
    11.       psa++;
    12.     }
    13.   return (int)(sarr-psa);
    14. }
    тоже не проверял. в конце может 'return (int)(sarr-psa)/sizeof(char*)' надо..
     
  11. dag

    dag New Member

    Публикаций:
    0
    Регистрация:
    17 авг 2004
    Сообщения:
    446
    Код (Text):
    1. #include <stdlib.h>
    2. #include <pcre.h>
    3.  
    4. int main()
    5. {
    6.   const char *errptr;
    7.   int erroffset;
    8.   const char *ababa="ababa q.1 w.2";
    9.   int ovector[1025];
    10.   int i;
    11.   int position=0;
    12.   int length=strlen(ababa);
    13.   pcre *compiled=pcre_compile("\\s*", 0, &errptr, &erroffset,NULL);
    14.  
    15.   if (compiled!=NULL)
    16.   {
    17.     while (position<length)
    18.     {
    19.       int recursives_count=pcre_exec(compiled,NULL,ababa,length,position,0,ovector,1024);
    20.       if (recursives_count<1) break;
    21.       for (i=0;i<recursives_count;i++)
    22.       {
    23.         char *substring_start=(char *)ababa+ovector[2*i];
    24.         int substring_length=ovector[2*i+1]-ovector[2*i];
    25.         printf("%2d[%i-%i]: [%.*s]\n", i,ovector[2*i],ovector[2*i+1],substring_length,substring_start);
    26.       };
    27.       position  =  ovector[1]  +  1;
    28.     };
    29.     pcre_free(compiled);
    30.   };
    31.  
    32.   return 0;
    33. };
    для \s*
    Код (Text):
    1.    0[0-0]: []
    2.  0[1-1]: []
    3.  0[2-2]: []
    4.  0[3-3]: []
    5.  0[4-4]: []
    6.  0[5-6]: [ ]
    7.  0[7-7]: []
    8.  0[8-8]: []
    9.  0[9-10]: [ ]
    10.  0[11-11]: []
    11.  0[12-12]: []
    для \s+
    Код (Text):
    1.    0[5-6]: [ ]
    2.    0[9-10]: [ ]
    для \w+
    Код (Text):
    1.  0[0-5]: [ababa]
    2.  0[6-7]: [q]
    3.  0[8-9]: [1]
    4.  0[10-11]: [w]
    5.  0[12-13]: [2]
    для [a-zA-Z\.0-9]+
    Код (Text):
    1.  0[0-5]: [ababa]
    2.  0[6-9]: [q.1]
    3.  0[10-13]: [w.2]
    В коде есть небольшая ошибка , но думаю из него понятно как что работает =)

    P.S.
    ещё раз советую обратиться к man perlretut + man pcre + примеры из самого pcre

    P.P.S.
    Извини за многа букаф -)
     
  12. _basmp_

    _basmp_ New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2005
    Сообщения:
    2.939
    dag
    Только-что посмотрел. У меня в вызове pcre_exec третьим параметром с конца (как называется не помню) стоит PCRE_NOTEMPTY.
     
  13. loginrl_103

    loginrl_103 New Member

    Публикаций:
    0
    Регистрация:
    8 фев 2008
    Сообщения:
    271
    всем спасибо) разобрался )