3

我们的 C++ 项目的日志记录工具即将重构为使用重复的左移运算符(以 QtqDebug()语法的方式)而不是 printf 样式的可变参数函数。

假设日志记录对象被调用logger。假设我们要显示我们连接的服务器的 ip 和端口。在当前的实现中,用法是:

logger.logf("connected to %s:%d", ip, port);

重构后,上述调用将变为:

logger() << "connected to" << ip << ":" << port;

手动替换所有这些调用将非常繁琐且容易出错,所以很自然地,我想使用正则表达式。作为第一遍,我可以替换.logf(...)调用,产生

logger() "connected to %s:%d", ip, port;

但是,将此字符串重新格式化为左移语法是我遇到问题的地方。我设法创建了单独的正则表达式来捕获printf 占位符逗号分隔的参数。但是,我不知道如何正确地将两者关联起来。

为了避免重复相当笨拙的正则表达式,我将使用占位符(printf)来引用printf 占位符正则表达式(返回命名的 group token),并(args)引用逗号分隔的参数正则表达式(返回命名的 group arg)。下面,我将给出应用于上述行相关部分的各种尝试的输出,即:

"connected to %s:%d", ip, port
  • /(printf)(args)/g不产生匹配。

  • /(printf)*(args)/g产生两个匹配,包含ipport在命名组中arg(但没有在token)。

  • /(printf)(args)*/g得到相反的结果:它产生两个匹配,在命名的 group中包含%s和,但在.%dtokenarg

  • /(printf)*(args)*/g返回 3 个匹配项:前两个包含%s%din token,第三个包含portin arg。但是,regexp101 报告“20 个匹配项 - 207 个步骤”并且似乎在每个字符之前都匹配。

  • 我想也许我需要指定第一个捕获组总是在双引号之间。但是,既不/"(printf)"(args)/g也不/"(printf)(args)/g产生任何匹配。

  • /(printf)"(args)/g产生一个(不正确的)匹配,包含%din grouptokenipin arg,并且替换会消耗这两个字符串之间的整个字符串(因此输入#替换字符串会导致"connected to %s:#, port. 显然,这不是预期的结果,但它是我可以的唯一版本至少在一次比赛中获得两个命名组。

任何帮助是极大的赞赏。

编辑以纠正损坏的格式

4

1 回答 1

0

免责声明:这是一种解决方法,它远非完美可能会导致错误。提交更改时要小心,如果可以,请让同事校对差异以减少干扰的机会。


您可以尝试从解决方案中的最大参数数量到最小值(这里我将从 3 到 0)进行多步替换。

让我们考虑一下logger.logf("connected to %s:%d some %s random text", ip, port, test);

您可以将此与此正则表达式匹配:logger.logf\("(.*?)(%[a-z])(.*?)(%[a-z])(.*?)(%[a-z])(.*?)",(.*?)(?:, (.*?))?(?:, (.*?))?\);它将为您提供以下组:

1.  [75-88] `connected to `
2.  [88-90] `%s`
3.  [90-91] `:`
4.  [91-93] `%d`
5.  [93-99] ` some `
6.  [99-101]    `%s`
7.  [101-113]   ` random text`
8.  [115-118]   ` ip`
9.  [120-124]   `port`
10. [126-130]   `test`

替换为logger() << "\1" << \8 << "\3" << \9 << "\5" << \10 << "\7";会给你

logger() << "连接到 " << ip << ":" << port << " some " << test << " random text";


现在使用 2 个参数,示例字符串是logger.logf("connected to %s:%d some random text", ip, port);,对应的正则表达式是logger.logf\("(.*?)(%[a-z])(.*?)(%[a-z])(.*?)",(.*?)(?:, (.*?))?\);

匹配如下:

1.  [13-26] `connected to `
2.  [26-28] `%s`
3.  [28-29] `:`
4.  [29-31] `%d`
5.  [31-48] ` some random text`
6.  [50-53] ` ip`
7.  [55-59] `port`

替换字符串:logger() << "\1" << \6 << "\3" << \7 << "\5";输出:

logger() << "连接到 " << ip << ":" << port << " 一些随机文本";


输入logger.logf("Some %s text", port);

正则表达式logger.logf\("(.*?)(%[a-z])(.*?)",(.*?)\);

替代品logger() << "\1" << \4 << "\3";

记录器()<<“一些”<<端口<<“文本”;


空组呢?

假设输入不是logger.logf("Some %s text", port);但是logger.logf("Some %s", port);。输出将是:

记录器()<<“一些”<<端口<<“”;

你必须删除<< ""才能得到干净的东西。

于 2016-07-08T07:40:28.100 回答