仅用一个正则表达式进行多次替换

2024-03-05

为了简单起见,假设我们有以下字符串:

“约翰爱玛丽,玛丽爱杰克,而杰克不关心约翰和玛丽。”

假设我想使用正则表达式来更改该故事的角色。

约翰 -> 约瑟夫

玛丽 -> 杰西卡

杰克 -> 基思

当然,我可以一次更改其中一项。

但我想知道是否可以仅用一个正则表达式替换来更改所有这些,例如“多个替换”或“条件替换”。

就像是:

regex: (?:(?<name1>John)|(?<name2>Mary)|(?<name3>Jake))

替代品:(?(name1)Joseph|(?(name2)Jessica|(?(name3)Keith)))

这只是一个简单的例子。

在我的应用程序中,我必须对每个字符串执行大约 20 次替换,这会影响应用程序的性能。

我使用的正则表达式风格是 PCRE。

该应用程序使用 C++ 和 Qt 框架进行编码。


所以你正在使用所谓的PCRE风味。很好,只是这并没有确切说明您正在使用哪个库。让我们回顾一下这里的几个选项,因为几个不同的库声称与 Perl 兼容。

Boost

这是最简单的解决方案。boost::regex完全支持您通过其要求的内容Boost 扩展格式字符串语法 http://www.boost.org/doc/libs/1_59_0/libs/regex/doc/html/boost_regex/format/boost_format_syntax.html.

所以你可以替换模式:

(?<name1>John)|(?<name2>Mary)|(?<name3>Jake)

使用替换字符串:

(?{name1}Joseph:(?{name2}Jessica:Keith))

当然,它有效。您可以在 Notepad++ 中测试它,但这里有一些示例代码:

#include <string>
#include <iostream>
#include <boost/regex.hpp>

int main(int argc, char **argv) {
    std::string subject("John loves Mary, Mary loves Jake and Jake doesn't care about John and Mary.");
    const char* replacement = "(?{name1}Joseph:(?{name2}Jessica:Keith))";

    boost::regex re("(?<name1>John)|(?<name2>Mary)|(?<name3>Jake)", boost::match_perl);

    std::string result = boost::regex_replace(subject, re, replacement, boost::format_all);
    std::cout << result << std::endl;

    return 0;
}

PCRE2

PCRE 赶上了 https://bugs.exim.org/show_bug.cgi?id=1689与 Boost 一起引入了更丰富的替换语法PCRE2_SUBSTITUTE_EXTENDED。截至本文 (v10.20),此代码尚未发布,但可以在源代码存储库(修订版 381)中找到,因此如果您现在需要此解决方案,则必须从源代码构建 PCRE2。

模式相同,但替换字符串具有不同的语法:

${name1:+Joseph:${name2:+Jessica:Keith}}

下面是一些示例 C 代码:

#include <stdio.h>
#include <string.h>

#define PCRE2_CODE_UNIT_WIDTH 8
#include <pcre2.h>

int main(int argc, char **argv) {
    int error;
    PCRE2_SIZE erroffset;

    const PCRE2_SPTR pattern = (PCRE2_SPTR)"(?<name1>John)|(?<name2>Mary)|(?<name3>Jake)";
    const PCRE2_SPTR subject = (PCRE2_SPTR)"John loves Mary, Mary loves Jake and Jake doesn't care about John and Mary.";
    const PCRE2_SPTR replacement = (PCRE2_SPTR)"${name1:+Joseph:${name2:+Jessica:Keith}}";

    pcre2_code *re = pcre2_compile(pattern, PCRE2_ZERO_TERMINATED, 0, &error, &erroffset, 0);
    if (re == 0)
        return 1;

    pcre2_jit_compile(re, PCRE2_JIT_COMPLETE);

    PCRE2_UCHAR output[1024] = "";
    PCRE2_SIZE outlen = sizeof(output) / sizeof(PCRE2_UCHAR);

    int rc = pcre2_substitute(re, subject, PCRE2_ZERO_TERMINATED, 0, PCRE2_SUBSTITUTE_GLOBAL | PCRE2_SUBSTITUTE_EXTENDED, 0, 0, replacement, PCRE2_ZERO_TERMINATED, output, &outlen);
    if (rc >= 0)
        printf("%s\n", output);

    pcre2_code_free(re);
    return 0;
}

PCRE

对于 PCRE (

...这意味着如果这是您正在使用的库,那么无论如何您都将完全控制替换过程。您可以使用如下模式:

John(*MARK:1)|Mary(*MARK:2)|Jake(*MARK:3)

然后,通过区分最后遇到的来替换MARK.

Qt

Qt's QRegularExpression类封装了 PCRE 库(不是 PCRE2),但它似乎并没有公开所有 PCRE 功能。

无论如何,QString::replace超载 http://doc.qt.io/qt-5/qstring.html#replace-12它接受一个QRegularExpression看起来功能并不齐全:

QString & QString::replace(const QRegularExpression & re, const QString & after)

所以你只能靠你自己了。

我的2分钱

嘿,也许对于这样一个简单的替换,正则表达式有点矫枉过正...如果您遇到性能问题,您应该尝试手动实现这些替换 - 精心设计的算法应该比正则表达式解决方案更快。只需确保分析您的代码并查看罪魁祸首在哪里。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

仅用一个正则表达式进行多次替换 的相关文章

  • 使用正则表达式、PHP 解析日志文件

    我对正则表达式非常糟糕 谁能帮我解决我需要的表达式 以便从日志文件中分离出我需要的两个值 日志文件示例 1 28 2013 8 43 22 PM Removed 178 76 234 41 1 28 2013 8 43 22 PM Remo
  • 从字符串中删除货币符号并使用 Javascript 中的单行转换为数字

    我下面有一个字符串 它是以英镑为单位的价格 我想删除货币符号 然后将其转换为我可以用来与另一个值进行比较的数字 价格 例如 X gt Y 14 50 我之前已将字符串转换为用于货币的数字 var priceNum parseFloat pr
  • 密码验证 PHP 正则表达式

    我是正则表达式的新手 我需要使用 php 验证密码 并使用正则表达式执行以下密码策略 密码 必须至少有 8 个字符 必须有2个号码 允许的符号有 我已经尝试过以下方法 d A Za z 0 9A Za z 以下完全符合您的要求 d d 0
  • python中匹配3个或更多相同的字符

    我正在尝试使用正则表达式在字符串中查找三个或更多相同的字符 例如 你好 不匹配 噢 会的 我尝试过做类似的事情 re compile 1 3 a zA Z re compile w 1 5 但似乎都不起作用 w 1 2 是您正在寻找的正则表
  • 如何使用正则表达式进行正确的输入验证?

    我想让用户只输入整数或浮点数 现在我只能输入整数 它允许输入点或逗号 无法找到正确的正则表达式来验证整数和浮点数
  • 多语言网站的 .htaccess 规则

    我正在重新设计 PHP 多语言网站 en es de fr ru 的 URL 该网站的 URL 是这样的 www mysite com page www mysite com page subpage1 www mysite com pag
  • Perl 中字符串之间的字符匹配计数

    我有一个字符串 例如字符串 1 需要与另一个字符串 字符串 2 匹配 两个字符串的长度相同并且不区分大小写 我想打印两个字符串之间的字符匹配数 E g String 1 stranger String 2 strangem Match co
  • 将 Javascript 正则表达式转换为 PHP

    我知道这个问题已经被问了大约十几次 但是从技术上讲 这个问题并不是一个骗局 如果您愿意 请检查其他问题 基本上 我有一个 Javascript 正则表达式来检查用于前端验证的电子邮件地址 并且我使用 CodeIgniter 在后端进行双重检
  • Google Analytics 正则表达式排除短语

    我正在使用以下 URL 创建内容分组 my category something my category somethingelse my category product1 brand color my category product2
  • 正则表达式没有按预期工作?

    我有这个正则表达式 new RegExp a z 0 9 ig 我正在测试一个不应该工作的字符串 vc 但它确实通过了测试 而且它不应该 new RegExp a z 0 9 ig test vc true 但如果我删除其中一个 or or
  • 将文本中的所有 URL 替换为 PHP 中的可点击链接[重复]

    这个问题在这里已经有答案了 我有一个用 PHP 编写的 Web 应用程序 我想找到用户评论中的所有 URL 并将它们更改为可点击的链接 我搜索了很多网站和页面 找到了以下解决方案 不幸的是我没有再次找到它的参考链接 感谢其作者 该代码可以完
  • PHP:检查任何基于拉丁语的语言中的字母字符?

    使用 PHP 我想检查一个字符串仅包含字母字符 我不想允许任何数字或特殊字符 例如 ctype alpha 对于这个目的来说似乎很棒 问题是我想允许重音字母 例如法语等 例如 我想允许 L rien 我知道ctype alpha 可以与se
  • emacs 临时文件的 .gitignore 正则表达式

    我正在尝试 gitignore emacs 临时 自动保存文件 我在用着 在我的 gitignore 中 But git add A在子文件夹中运行仍然给我 new file make collections py new file nor
  • csv格式是常规语法还是上下文无关语法?

    我目前正在编写一个 csv 解析器 csv 格式的定义由下式给出RFC4180 https www rfc editor org rfc rfc4180这是由 ABNF 定义的 所以csv的定义绝对是上下文无关语法 不过我想知道csv是否是
  • 匹配不包含超过 x 个连续字符的字符串的正则表达式是什么

    我想要匹配不包含连续 3 个以上重复的相同字符的字符串 所以 abaaaa 不匹配 abawdasd 比赛 abbbbasda 不匹配 巴巴巴巴 比赛 是的 对包含连续字符进行正则表达式匹配 然后在代码中对其进行否定会更容易 更简洁 然而
  • Bash - 在 perl 正则表达式中使用变量以及匹配组

    这是我在 stackoverflow 上的第一篇文章 如果我错过了一些重要的内容 请原谅我 我目前遇到以下问题 目标是根据我准备的文件列表动态替换端口号find 这些文件中的所有端口均以数字 4 开头 有 5 位数字 现在是棘手的部分 我只
  • 以点作为分隔符分割字符串

    我想知道我是否要在一个字符串上分割字符串 正确的方式 我的代码是 String fn filename split return fn 0 我只需要字符串的第一部分 这就是我返回第一项的原因 我问这个是因为我在 API 中注意到 意味着任何
  • Python正则表达式替换除特定单词之外的所有内容

    我正在尝试执行以下操作用正则表达式 import re x re compile going you words to replace s I am going home now thank you string to modify pri
  • YouTube 频道 URL 的正则表达式

    如何使用 REGEX 验证 YouTube 频道 URL 我发现了这个模式 但它不能正常工作 http https www youtube com channel user a zA Z0 9 1 谁能帮我 你的问题是之后的额外管道user
  • Python 正则表达式从文本中提取域

    我有以下正则表达式 r a zA Z0 9 a zA Z0 9 61 a zA Z0 9 a zA Z 2 6 当我将其应用于文本字符串时 比方说 这是 www website1 com 这是 website2 com 我得到 www we

随机推荐