2012-03-27 3 views
0

정규식을 더 빨리 잊어 버렸습니다. 주요 PITA입니다. 어쨌든 HTTP 응답 상태 라인을 구문 분석하고 하위 요소를 올바르게 캡처하도록 RE를 원했습니다. 나는이 일을 얻었다 :부스트 정규 표현식을 사용하여 텍스트 토큰 화

const boost::regex status_line("HTTP/(\\d+?)\\.(\\d+?) (\\d+?) (.*)\r\n"); 
    std::string status_test1("HTTP/1.1 200 hassan ali\r\n"); 

    boost::smatch what; 
    std::cout << regex_match(status_test1,what, status_line, boost::match_extra) << std::endl; 
    std::cout << what.size() << std::endl; 

    BOOST_FOREACH(std::string s, what) 
    { 
    std::cout << s << std::endl; 
    } 

네 번째 캡처 그룹은 특히 단어를 토큰 화하는 것과 관련이있다. 하지만 내 일이 끝나기 위해 나는 그것을 필요로하지 않는다. 그러나, 나는 여전히 '\ 0'으로 끝나는 공간 분리 된 문장을 토큰 화하는 방법을 알고 싶다. 스트립 된 단어의 벡터/배열이된다.

나는 다음과 같은 단편은이 "hassan ali syed " 일치하지해야

const boost::regex sentence_re("(.+?)((.+?))*"); 
    boost::smatch sentence_what; 
    std::string sentence("hassan ali syed "); 

    std::cout << boost::regex_match(sentence,sentence_what,sentence_re, boost::match_extra) << std::endl; 

    BOOST_FOREACH(std::string s, sentence_what) 
    { 
    std::cout << s << std::endl; 
    } 

을 작동시킬 수는 없지만, "hassan ali syed" 일치해야하고, 캡처 그룹해야한다 (줄 바꿈 포함) 출력 hassanalisyed, 그러나 그것을 출력 hassansyedsyed (주, 세 번째 셰 <space>syed의 공간. 내가 캡처 그룹이 재귀 개체를 처리 할 수없는 가정?

그래서 PCRE 구문에서 토큰 화 작업을 지정하는 깨끗한 토큰 벡터가 생성됩니다 (반복하지 않고 - 즉, 중첩 그룹이 공백을 제거하려고하지 않음).

나는 이것이 직업에 적합한 도구가 아니라는 것을 알고있다. spirit/lexx 또는 boost :: tokenise가 가장 좋으며, 그것에 대해 올바른 방법이 아니라는 것을 알고있다. .net에서 스크린 스크래핑을 할 때 토큰이 다 떨어질 때까지 반복적으로 정규 표현식을 본문에 적용하여 텍스트 본문에 토큰을 찾습니다.

답변

1

이것은 비슷한 질문 인 Capturing repeating subpatterns in Python regex을 상기시켜줍니다.

물론이다
"HTTP/(\\d+?)\\.(\\d+?) (\\d+?) ([^ ]+\s)?([^ ]+\s)?([^ ]+\s)?([^ ]+\s)?\n\r" 

, 끔찍한 :

공백으로 구분 된 단어의 수는 토큰의 일부 최대 수를 제한하는 경우

는, 당신은 단지 약간 같은 별도의 서브 패턴의 전체 무리에 압정 수 있습니다 .

이 당신의 정규 표현식 구현 "반복 서브 패턴"지원 (링크 된 질문에서 사용 된 파이썬의 표준이 아닌 regex 모듈을 참조하십시오.) 당신은 거의 확실하다없이 할 수 생각하지 중첩 된 그룹을 원한다면, 내가 할 초보자를위한 문자열 함수를 사용하면 더 편리합니다. 현지에서 사용하는 string.split()과 같습니다.

+0

참고 : 나는 C++ 또는 부스트 :: 정규 표현식 사용자가 아닙니다. –

0

부스트가 재귀 적 그룹화를 수행 할 수도 있지만 확실하지는 않습니다. 나는 그것을 향한 경향이 없다.
난 그저 할 수있는 .NET 알고.

두 부분으로 된 하나의 정규식을 디자인 할 수 있습니다. 첫 번째 부분은 특정 그룹을 캡처하고 두 번째 부분은 단일 그룹에서 나머지를 캡처합니다. 그런 다음 캡처 된 두 번째 부분에서 다른 재귀 적 정규식을 수행 할 수 있습니다. 이 같은

뭔가 :
(specific)(part)(to)(capture)(all the remaining text)

그런 다음 잠시 할 (/ (부분) /) 이전 나머지 텍스트 캡처에 정규식.여기

는 부스트에서 그것을 할 수있는 방법 -

const string status = "HTTP/1.1 200 hassan ali\r\n"; 

boost::regex rx_sentence ("HTTP/(\\d+)\\.(\\d+)\\s+(\\d+)\\s*([^\\s]+(?:\\s+[^\\s]+)*)?.*"); 
boost::regex rx_token ("[^\\s]+"); 

if (boost::regex_match(status, what, rx_sentence)) 
{ 
    std::cout << "\nMatched:\n-----------------\n" << "'" << what[0] << "'" << std::endl; 

    std::cout << "\nStatus (match groups):\n-----------------" << std::endl; 
    for (int i=1; i < 4; i++) 
    { 
     std::cout << i << " = '" << what[i] << "'" << std::endl; 
    } 
    std::cout << "\nTokens (search of group 4):\n-----------------" << std::endl; 
    const string token_str = what[4]; 

    std::string::const_iterator start = token_str.begin(); 
    std::string::const_iterator end = token_str.end(); 

    while (boost::regex_search(start, end, what, rx_token)) 
    { 
     string token(what[0].first, what[0].second); 
     cout << "'" << token << "'" << endl; 
     start = what[0].second; 
    } 
} 
else 
    std::cout << "Didn't match" << std::endl;