我有一个约1000000字的文本(只是一个例子),我想在一次迭代中解析它。而我想要做的是每次表达式匹配时,将其更改为其他内容。例如:
表达式:
| Expression | New text |
|----------------|----------|
| ab | A |
| #{1,3}cb | B |
| [1234567890]db | C |
文字:
Lorem ipsum dolor sit amet, ## cb consectetur adipiscing elit。结肠前膜韧带结构 #cb ,原始的laoreet ligula ultrices。在quis aliquam urna中,在 ab suscipit purus中。 Nunc posuere efficitur 9db nibh,tempor convallis mauris porta lobortis。
将输出文字:
Lorem ipsum dolor坐下来, B consectetur adipiscing elit。结肠前膜韧带 B ,原始的laoreet ligula ultrices。在quis aliquam urna中,在 A suscipit purus中。 Nunc posuere efficitur C nibh,tempor convallis mauris porta lobortis。
假设这些“常规”表达式不会相互重叠,有没有办法在c ++中使用std::regex
实现这个?
我试过这样做,但有两个主要问题:
有没有办法解决这个问题,或者最好的解决方案是为这个特定目的编写解析器
答案 0 :(得分:2)
正如EJP所说,即使你对解析器生成器一无所知,使用(f)lex也是微不足道的。 (你应该稍微看一下flex idiosyncratic regular expression syntax。就像每个面向正则表达式的工具一样,它有自己的怪癖。)
这是一个适合您任务的完整弹性计划:
%option noinput nounput noyywrap
%%
ab { fputs("A", stdout); }
"#"{1,3}cb { fputs("B", stdout); }
[0-9]db { fputs("C", stdout); }
最后一行可能是[1234567890]
,但[0-9]
和[[:digit:]]
更为惯用。如倒数第二行所示,通过将特殊字符放在引号内引用特殊字符是很正常的,这是正则表达式工具所允许的。请注意,"abc"*
是" abc
"的任意数量的重复,与abc*
完全不同。
最大的限制是没有捕获,虽然这似乎与您的问题无关,并且几乎总是有简单的解决方法。
编译并运行:
$ flex -o replacer.c replacer.l
$ gcc -o -Wall replacer replacer.c -lfl
$ ./replacer < lorem
Lorem ipsum dolor sit amet, Bconsectetur adipiscing elit. Vestibulum
posuere ligula in diam volutpat B, vitae laoreet ligula ultrices. In
quis aliquam urna, in A suscipit purus. Nunc posuere efficitur C nibh,
tempor convallis mauris porta lobortis.
我已经知道构建生成,编译和运行flex程序的快速而肮脏的工具,因为当输入文件很大时,结果可能比从标准实用程序中将事物拼凑在一起要快得多。例如,请参阅this answer on a companion site,它会向微型flex程序添加实际的main
,以避免依赖-lfl
。
答案 1 :(得分:0)
我不知道如何使用std :: regex执行此操作,但您可以尝试使用boost :: iostreams :: regex_filter。来自their site的示例仅使用一个过滤器,但我相信您可以使用更多。例子:
#include <boost/iostreams/device/array.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/filter/regex.hpp>
#include <boost/regex.hpp>
#include <iostream>
using namespace boost::iostreams;
int main()
{
char buffer[16];
array_sink sink{buffer};
filtering_ostream os;
os.push(regex_filter{boost::regex{"Bo+st"}, "C++"});
// push more filters here
os.push(sink);
os << "Boost" << std::flush;
os.pop();
std::cout.write(buffer, 3);
}
需要注意的是,根据文档,它会立即将所有文本读入内存。你的100万字应该不是问题,但对于千兆字节大小的文件,你可能遇到问题。
如果是我,我会手工替换,因为它可能不那么复杂。
答案 2 :(得分:0)
这是你可以做的。
设r1,r2,...,rn是你的正则表达式,r是它们的交替(r1)|(r2)| ... |(rn)。