【问题标题】:Regex substitution: Replace texts, not codes正则表达式替换:替换文本,而不是代码
【发布时间】:2020-10-22 06:42:49
【问题描述】:

我几天来一直在尝试解决一个正则表达式测验,但仍然无法正确解决。我已经很接近了,但仍然无法通过。

任务:

在 HTML 页面中,将文本 micro 替换为 µ。哦,不要搞砸代码:不要在 <the tags>&entities; 内部替换

替换

  • micro -> µ
  • abc micro -> abc µ
  • micromicro -> µµ
  • µmicro -> µµ

请勿触摸

  • <tag micro /> -> <tag micro />
  • µ -> µ
  • &abcmicro123; -> &abcmicro123;

I tried this 但在最后一个µ 上失败了,我错过了什么?有人能指出我错过了什么吗?提前致谢!

我尝试过的:

正则表达式

((?:\G|\n)(?:.*?&.*?micro.*?;[\s\S]*?|.*?<.*?micro.*?>[\s\S]*?|.)*?)micro

替换

$1&micro;

【问题讨论】:

  • Regex 不是解析 HTML 的正确工具
  • 使用正则表达式真的很难。如果您不想在某些情况下进行匹配,则必须使用否定的lookbehind,但它们必须是固定大小,因此您不能使其在&lt;tag 之后的任何地方都不匹配。
  • 这是一个quiz on regex101。我能感觉到这真的很难解决,但也许我一开始就走错了路。只需要一个正确方向的提示。
  • 祝你好运。想想 HTML cmets、脚本标签、CDATA、值中具有 &gt; 的属性等等,等等……如前所述,正则表达式不是解析 HTML 的正确工具。

标签: regex pcre substitution


【解决方案1】:

你可以试试这样的:

(?:&lt;.*?&gt;|&amp;\w++;)(*SKIP)(*F)|micro

替换字符串:

&amp;micro;

【讨论】:

    【解决方案2】:

    使用SKIP-FAIL technique,但作为一个整体匹配:

    (?:<[^<>]*>|&\w+;)(*SKIP)(*F)|\bmicro\b
    

    proof

    说明

    --------------------------------------------------------------------------------
      (?:                      group, but do not capture:
    --------------------------------------------------------------------------------
        <                        '<'
    --------------------------------------------------------------------------------
        [^<>]*                   any character except: '<', '>' (0 or
                                 more times (matching the most amount
                                 possible))
    --------------------------------------------------------------------------------
        >                        '>'
    --------------------------------------------------------------------------------
       |                        OR
    --------------------------------------------------------------------------------
        &                        '&'
    --------------------------------------------------------------------------------
        \w+                      word characters (a-z, A-Z, 0-9, _) (1 or
                                 more times (matching the most amount
                                 possible))
    --------------------------------------------------------------------------------
        ;                        ';'
    --------------------------------------------------------------------------------
      )                        end of grouping
    --------------------------------------------------------------------------------
      (*SKIP)(*F)              Skip the match and go on matching from current location
    --------------------------------------------------------------------------------
     |                        OR
    --------------------------------------------------------------------------------
      \b                       the boundary between a word char (\w) and
                               something that is not a word char
    --------------------------------------------------------------------------------
      micro                    'micro'
    --------------------------------------------------------------------------------
      \b                       the boundary between a word char (\w) and
                               something that is not a word char
    

    【讨论】:

    • 甚至不知道这些标志的存在。这让事情变得容易多了。感谢您让我走上正轨和详细的解释!但我会接受另一个答案,因为他早些时候发布了答案。
    • @HaoWu 是的,总是接受最适合你的。感谢您提出一个很好的问题,+1。
    【解决方案3】:

    var strings = [
        "micro",
        "abc micro",
        "micromicro",
        "&micro;micro",
        "<tag micro />",
        "&micro;",
        "&abcmicro123;"
    ];
    var re = /(?<!(<[^>]*|&[^;]*))(micro)/g;
    strings.forEach(function(str) {
        var result = str.replace(re, '&$2;')
        console.log(str + ' -> ' + result)
    });

    控制台日志输出:

    micro -> &micro;
    abc micro -> abc &micro;
    micromicro -> &micro;&micro;
    &micro;micro -> &micro;&micro;
    <tag micro /> -> <tag micro />
    &micro; -> &micro;
    &abcmicro123; -> &abcmicro123;
    

    解释:

    • 使用(?&lt;!...) - 消极的后视排除内部标签或实体
    • (&lt;[^&gt;]*|&amp;[^;]*) - 在负前瞻内跳过 &lt;...&gt; OR '&...;'
    • (micro) - 捕获你的标签(根据需要添加多个,例如(micro|brewery)
    • '&amp;$2;' - 替换将捕获的标签变成一个实体&amp;...;

    【讨论】:

    • 不幸的是,pcre 正则表达式不支持非固定宽度的回溯:(否则会容易得多
    猜你喜欢
    • 2014-03-11
    • 1970-01-01
    • 1970-01-01
    • 2013-10-06
    • 1970-01-01
    • 2016-11-12
    • 2017-10-18
    • 2017-01-21
    • 2019-11-29
    相关资源
    最近更新 更多