我正在尝试执行以下基于C ++ STL的代码来替换相对较大的SQL脚本中的文本(~8MB):
std::basic_regex<TCHAR> reProc("^[ \t]*create[ \t]+(view|procedure|proc)+[ \t]+(.+)$\n((^(?![ \t]*go[ \t]*).*$\n)+)^[ \t]*go[ \t]*$");
std::basic_string<TCHAR> replace = _T("ALTER $1 $2\n$3\ngo");
return std::regex_replace(strInput, reProc, replace);
结果是堆栈溢出,并且很难在此特定站点上找到有关该特定错误的信息,因为这也是站点的名称。
编辑:我正在使用Visual Studio 2013 Update 5
编辑2:原始文件超过23,000行。我将文件减少到3,500行仍然得到错误。当我用另外约50行切割到3,456行时,错误就消失了。如果我只将那些切割线放入文件中,则错误仍然消失。这表明该错误与特定文本无关,但与其过多有关。
编辑3 :完整的工作示例在此处运行正常: https://regex101.com/r/iD1zY6/1 但它在STL代码中不起作用。
答案 0 :(得分:2)
根据regex101,正则表达式的以下修剪版本可以节省大约20%的处理步骤(参见here)。
\\bcreate[ \t]+(view|procedure|proc)[ \t]+(.+)\n(((?![ \t]*go[ \t]*).*\n)+)[ \t]*go[ \t]*
修改:
如果你能确定......
create ...
语句不会出现在字符串文字中,
您无需区分create ...
后跟go
的语句(例如,因为所有语句都落后于go
)
......替换这些字符串可能更容易:
std::basic_regex<TCHAR> reProc("\bcreate[ \t]+(view|procedure|proc)");
std::basic_string<TCHAR> replace = _T("ALTER $1");
return std::regex_replace(strInput, reProc, replace);
(Here是后一种方法的演示 - 将步骤减少到1/4以上。
答案 1 :(得分:1)
事实证明,STL正则表达式与Perl相比是悲剧性的表现不佳(如果你能相信https://stackoverflow.com/a/37016671/78162,大约慢100倍),所以显然有必要绝对最小化正则表达式的使用。 STL / C ++当性能受到严重关注时。 (考虑到我认为C ++通常是性能更高的语言之一),C ++ / STL在这里表现不佳的程度让我大吃一惊。我最终传递文件流一次读取一行,只在需要处理的行上运行表达式:
std::basic_string<TCHAR> result;
std::basic_string<TCHAR> line;
std::basic_regex<TCHAR> reProc(_T("^[ \t]*create[ \t]+(view|procedure|proc)+[ \t]+(.+)$"), std::regex::optimize);
std::basic_string<TCHAR> replace = _T("ALTER $1 $2");
do {
std::getline(input, line);
int pos = line.find_first_not_of(_T(" \t"));
if ((pos != std::basic_string<TCHAR>::npos)
&& (_tcsnicmp(line.substr(pos, 6).data(), _T("create"), 6)==0))
result.append(std::regex_replace(line, reProc, replace));
else
result.append(line);
result.append(_T("\n"));
} while (!input.eof());
return result;