以下是我在MFC应用程序中用于检查正则表达式匹配的代码:
int CDouserApp::FindMatches(std::vector<std::wstring>& output,
const std::wstring& input,
const std::wstring& pattern)
{
std::tr1::wregex rx(pattern);
std::tr1::wsmatch results;
output.clear();
if (!(std::tr1::regex_search(input, results, rx)))
{
return 0;
}
for (auto& r : results)
{
output.push_back(r.str());
}
return output.size();
}
void CDouserView::OnClickedSearch()
{
std::vector<std::wstring> ret;
std::wstring pattern(this->regexList.GetWindowTextLength() + 1, 0);
this->regexList.GetWindowText(&pattern[0], pattern.length());
std::wstring input(this->inputEdit.GetWindowTextLength() + 1, 0);
this->inputEdit.GetWindowText(&input[0], input.length());
CDouserApp::FindMatches(ret, input, pattern);
this->resultsList.DeleteAllItems();
std::wstringstream resultsStatus;
resultsStatus << ret.size() << " result(s)";
static_cast<CMainFrame*>(::AfxGetMainWnd())->GetStatusBar()
.SetWindowText(resultsStatus.str().c_str());
for (auto& match : ret)
{
this->resultsList.InsertItem(LVIF_TEXT, match.c_str());
}
}
如果我使用<h(.)>([^<]+)
和<h2>Egg prices</h2>
作为输入,即使它与“2”和“鸡蛋价格”相匹配,我也会获得0结果。如果我使用Hello
作为正则表达式并使用Hello, world!
作为输入字符串,我得到0结果,即使它应该匹配“Hello”。
我甚至尝试将输入和模式转换为ASCII并使用非宽std::regex
系列,但结果是相同的。迄今为止匹配任何内容的唯一模式是.*
,它匹配整个字符串。
我知道gcc的正则表达式文件库坏了,但我之前使用过std :: regex和MSVC并没有出现问题。我想避免使用boost :: regex或pcre如果我可以避免它。
更新/修改:由于某种原因,此代码正常工作:
static void RegexTest(void)
{
std::tr1::wregex rx1(L"<h(.)>([^<]+)");
std::wstring input1(L"<h2>Egg prices</h2>");
std::tr1::wregex rx2(L"Hello");
std::wstring input2(L"Hello, world!");
std::tr1::wsmatch results;
if (!(std::tr1::regex_search(input1, results, rx1)))
{
::MessageBox(nullptr, L"No matches found", L"Done", MB_OK | MB_ICONASTERISK);
}
else
{
std::wstringstream s;
s << results.size() << " match(es) found:" << std::endl;
for (auto& m : results)
{
s << m.str() << std::endl;
}
::MessageBox(nullptr, s.str().c_str(), L"Done", MB_OK | MB_ICONINFORMATION);
}
if (!(std::tr1::regex_search(input2, results, rx2)))
{
::MessageBox(nullptr, L"No matches found", L"Done", MB_OK | MB_ICONASTERISK);
}
else
{
std::wstringstream s;
s << results.size() << " match(es) found:" << std::endl;
for (auto& m : results)
{
s << m.str();
}
::MessageBox(nullptr, s.str().c_str(), L"Done", MB_OK | MB_ICONINFORMATION);
}
}
最终更新(和解决方案):
经过大量分析和测试后,我发现我必须从字符串中删除空终结符:
void CDouserView::OnClickedSearch()
{
std::vector<std::wstring> ret;
std::wstring pattern(this->regexList.GetWindowTextLength() + 1, 0);
this->regexList.GetWindowText(&pattern[0], pattern.length());
pattern.resize(pattern.length() - 1);
std::wstring input(this->inputEdit.GetWindowTextLength() + 1, 0);
this->inputEdit.GetWindowText(&input[0], input.length());
input.resize(input.length() - 1);
CDouserApp::FindMatches(ret, input, pattern);
this->resultsList.DeleteAllItems();
std::wstringstream resultsStatus;
resultsStatus << ret.size() << " result(s)";
static_cast<CMainFrame*>(::AfxGetMainWnd())->GetStatusBar()
.SetWindowText(resultsStatus.str().c_str());
for (auto& match : ret)
{
this->resultsList.InsertItem(LVIF_TEXT, match.c_str());
}
}
问题是GetWindowText写入字符串同时还添加了一个空终止符; STL字符串认为此null终止符实际上是数据的一部分。我不知道为什么Dinkumware在输入字符串的末尾存在这个额外的null这么困难。我还没有用Boost测试它,看看它是否有相同的陷阱,但我怀疑它没有。
答案 0 :(得分:0)
您认为正则表达式分组符号()将提供匹配是错误的。这用于反向引用。这将匹配“<h2>dsdsd
”之类的内容。你想要的是一个正则表达式,它实际上代表了标签内部(完整的)文本。因为我不熟悉你正在使用的正则表达式...我不能为你提供它。
一切顺利。
答案 1 :(得分:0)
匹配函数不能像那样工作。
当您使用正则表达式<h(.)>([^<]+)
并检查匹配字符串<h2>Egg prices</h2>
时,正则表达式将检查正则表达式是否与整个字符串匹配,在这种情况下,这只会匹配<h2>Egg prices
而不是{{ 1}}(参见example here)。如果你想在字符串包含内部检测一些正则表达式,你应该在{I}之前和之后添加野性字符<h2>Egg prices</h2>
答案 2 :(得分:0)
str.resize(str.length() - 1);
从字符串中删除C样式的null终止符可以解决所有问题。它认为null是实际表达模式的一部分,导致它每次都失败。