使用 Boost::Regex 从文本文件中提取子字符串
Extracting substrings using Boost::Regex from textfile
所以我在许多不同的文本文件中有电子邮件,我需要从布局不一致的所述文件中提取它们。我正在使用 Boost::Regex
和 Boost::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
表示其他含义:
另外,\.
是一个非法的转义序列,所以你的编译器应该已经发出警告了。 (你需要\.
)
最后,我认为 \b
是 Perl-compatible 正则表达式。哦,你不只是想要大写的电子邮件,对吧。所以让我们修复它:
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"
所以我在许多不同的文本文件中有电子邮件,我需要从布局不一致的所述文件中提取它们。我正在使用 Boost::Regex
和 Boost::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
表示其他含义:
另外,\.
是一个非法的转义序列,所以你的编译器应该已经发出警告了。 (你需要\.
)
最后,我认为 \b
是 Perl-compatible 正则表达式。哦,你不只是想要大写的电子邮件,对吧。所以让我们修复它:
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"