c++ - 使用 Boost::Regex 从文本文件中提取子字符串

标签 c++ boost boost-regex

所以我有许多不同文本文件的电子邮件,我需要从布局不一致的所述文件中提取它们。我正在使用 Boost::RegexBoost::File-system 尝试读取它们,然后提取电子邮件地址。但是,它似乎无法查找或提取电子邮件。它可以匹配简单的单词,例如 email 或字母 a。但它似乎在实际读取文件时遇到了问题。

一个最小的例子如下(不包含):

#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._%+-]+@[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;
}

我不确定为什么它不起作用:电子邮件示例如下:

"radafwair@dasfsn.com","S"
"eliseoaafwafwlcon@mafwsn.com","R"
jjafwpawwafa2@csaot.net<br>

以及电子邮件在文本文件中的各种其他方式,我如何让这个正则表达式匹配?

最佳答案

正则表达式有缺陷。 \b 表示其他含义:

enter image description here

此外,\. 是非法的转义序列,因此您的编译器应该已经发出警告。 (你需要 \\.)

最后,\b 我认为是 Perl 兼容的正则表达式。哦,你不只是想要大写的电子邮件,对吧。所以让我们修复它:

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

也许使用 rfc822 解析器库会好一点:)

这是一段干净的代码:

#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._%+-]+@[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 文件系统,您将不会使用 extension() 访问函数来进行有缺陷的字符串操作
  • 尽可能减少条件的嵌套
  • 没有多余的文件关闭(这是 C++,文件在超出范围时关闭)
  • 不要为子匹配组而烦恼,因为您不使用它们
  • 打印匹配的 str()

在我的测试文件夹中打印(包括 stderr):

Reading "./input.txt"
    radafwair@dasfsn.com
    eliseoaafwafwlcon@mafwsn.com
    jjafwpawwafa2@csaot.net
Reading "./output.txt"
Reading "./big.txt"
Reading "./CMakeLists.txt"
Reading "./CMakeCache.txt"

关于c++ - 使用 Boost::Regex 从文本文件中提取子字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41774282/

相关文章:

c++ - VC++ 2008 编译问题与 boost

php - 如何在 C++ boost 中编写这些正则表达式?

c++ - 如何在 C++ 中连接 SVN 服务器?

c++ - 使用模板友元函数时未解析的重载函数类型

c++ - clang 3.3/Xcode & libc++:std::getline 在调用 ifstream::clear() 后不读取数据

c++ - 如何使用压缩器 Boost::Iostreams 过滤器作为 Boost::Log 中的接收器

c++ - 使用boost::smatch在valgrind中读取大小无效1

c++ - 使用 Boost C++ 库将正则表达式替换为自定义替换

c++ - 其他进程在 MPI_Sendrecv 之后挂起

c++ - 具有大整数的 mod % 运算符的局限性