2017-01-21 6 views
1

그래서 많은 다른 텍스트 파일로 전자 메일을 보내고 레이아웃에서 일관성이없는 파일에서 전자 메일을 추출해야합니다. Boost::RegexBoost::File-system을 사용하여 읽은 다음 전자 메일 주소를 추출합니다. 그러나 이메일을 찾거나 추출하는 데는 효과가없는 것 같습니다. 이 단어는 email 또는 a과 같은 간단한 단어와 일치 할 수 있습니다. 하지만 실제로 파일을 읽는 데 문제가있는 것 같습니다. 다음과 같이텍스트 파일의 Boost :: Regex를 사용하여 하위 문자열 추출

최소한의 예입니다 (더는 포함되지 않습니다) :

#include <fstream> 
#include <iostream> 
#include <sstream> 
#include <string> 

#include <boost/regex.hpp> 
#include <boost/foreach.hpp> 
#include <boost/filesystem.hpp> 


namespace fs = boost::filesystem; // File system is namespace. 

int main() { 
    boost::regex pattern("\b[A-Z0-9._%+-][email protected][A-Z0-9.-]+\.[A-Z]{2,}\b"); // Email regex to match. 
    boost::smatch result; 

    fs::path targetDir(boost::filesystem::current_path()); // Look in this folder. 
    fs::directory_iterator it(targetDir), eod;  // Iterate over all the files in said directory. 
    std::string line; 
    BOOST_FOREACH(fs::path const &p, std::make_pair(it, eod)) { // Actual iteration. 
     if (fs::is_regular_file(p)) { // What this does is checks if it's a normal file. 
      std::ifstream infile(p.string()); // Read file line by line. 
      if (p.string().substr(p.string().length() - 3) != "txt") { 
       continue; // Skip to next file if not text file. 
      } 
      while (std::getline(infile, line)) { 
       bool isMatchFound = boost::regex_search(line, result, pattern); 
       if (isMatchFound) 
       { 
        for (unsigned int i = 0; i < result.size(); i++) 
        { 
         std::cout << result[i] << std::endl; 
        } 
       } 
      } 
      infile.close(); 
     }  
    } 
    return 0; 
} 

가 작동하지 않는 이유를 잘 모르겠어요 :

"[email protected]","S" 
"[email protected]","R" 
[email protected]<br> 

그리고 다음과 같이 이메일의 샘플이 될 수 있습니다 전자 메일이 텍스트 파일에있을 수있는 다양한 방법,이 정규식을 어떻게 얻을 수 있습니까?

답변

3

정규식에 결함이 있습니다.

enter image description here

또한, \. 그래서 컴파일러는 경고해야, 불법 이스케이프 시퀀스입니다 : \b 다른 것을 의미한다. (\\.)

마지막으로, \b은 Perl 호환 정규식이라고 생각합니다. 오, 그리고 당신은 대문자 이메일을 원했던 것이 아닙니다. 맞습니다.

#include <boost/filesystem.hpp> 
#include <boost/range/iterator_range.hpp> 
#include <boost/regex.hpp> 
#include <fstream> 
#include <iostream> 
namespace fs = boost::filesystem; 

int main() { 
    boost::regex pattern("\\b[A-Z0-9._%+-][email protected][A-Z0-9.-]+\\.[A-Z]{2,}\\b", 
     boost::regex_constants::perl | boost::regex_constants::icase); // Email regex to match. 
    boost::smatch result; 
    std::string line; 

    for (fs::path p : boost::make_iterator_range(fs::directory_iterator("."), {})) { 
     if (!fs::is_regular_file(p) || p.extension() != ".txt") 
      continue; 

     std::cerr << "Reading " << p << "\n"; 

     std::ifstream infile(p.string()); // Read file line by line 
     while (std::getline(infile, line)) { 
      if (boost::regex_search(line, result, pattern)) { 
       std::cout << "\t" << result.str() << "\n"; 
      } 
     } 
    }  
} 

참고 :

boost::regex pattern("\\b[A-Z0-9._%+-][email protected][A-Z0-9.-]+\\.[A-Z]{2,}\\b", 
    boost::regex_constants::perl | boost::regex_constants::icase); // Email regex to match. 

은 아마도 RFC822 파서 라이브러리 : 여기

를 사용하는 것이 조금 더 좋을 것이다 코드의 청소 조각을 것 : 그래서 고칠 수 있습니다

  • 부스트 파일 시스템을 사용하는 경우 extension() 접근 자 기능을 사용하는 대신 결함있는 문자열 조작을 수행하지 않습니다.
  • 이 가능한 경우 상태의 중첩을 감소
  • 파일의 중복되는 폐쇄하지 않습니다 (이는 C++가 범위 밖으로 갈 때, 가까운 파일)
  • 이 submatch 그룹과 귀찮게하지 않습니다 당신이 그들을 사용하지 않기 때문에,
  • 내 테스트 폴더에 경기

str() 값을 인쇄하기 인쇄 (를 포함하여 표준 에러) :

Reading "./input.txt" 
    [email protected] 
    [email protected] 
    [email protected] 
Reading "./output.txt" 
Reading "./big.txt" 
Reading "./CMakeLists.txt" 
Reading "./CMakeCache.txt"