【问题标题】:How to replace phrases in a text for a given expression in JavaScript如何为 JavaScript 中的给定表达式替换文本中的短语
【发布时间】:2018-10-16 17:07:00
【问题描述】:

我编写了这个函数,目的是用指定的表达式 expr 替换 text 文档中的单词或短语,给定一组要匹配的 tokens。 文档采用换行格式。

function replaceTokens(text, tokens, expr, isline = false) {
  tokens.forEach(word => {
    if (expr[token]) {
      if (isline) { // line regex
        text = text.replace(new RegExp("(" + word.replace(/([\(\)'?*!"])/g, "\\$1") + ")", "gi"), expr);
      } else {
        text = text.replace(new RegExp("(" + word + ")", "gi"), expr[token]);
      }
    }
  });
  return text;
}

我面临两个问题。

1) 对于Loremquiwords 标记,它工作得很好,但我无法摆脱整个标记的情况,即我不想匹配 @987654328 @ 在像 quis 这样的单词中,但只有文本中的给定标记。在这里使用^word$ 不适用于捕获组^(word)$

[1 - SOLVED]根据new RegExp("\\b(" + word + ")\\b", "gi")的第一个答案

2) 对于 phrases 标记,我使用的正则表达式无法正常工作。 我想在

中匹配 Lorem ipsum dolor sit amet 这样的确切行
Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet etwas

它应该只匹配第一行,而不是第二行。

这是一个例子。对于 (1),您可以看到 qui 是如何被捕获为标记的,并且在单词 quisaliquip 中。

function replaceTokens(text, tokens, expr, isline = false) {
  tokens.forEach(word => {
    if (isline) { // line regex
      text = text.replace(new RegExp("(" + word.replace(/([\(\)'?*!"])/g, "\\$1") + ")", "gi"), expr);
    } else {
      text = text.replace(new RegExp("\\b(" + word + ")\\b", "gi"), expr);
    }
  });
  return text;
}

text = "Lorem ipsum dolor sit amet,\n consectetur adipiscing elit,\nsed do eiusmod tempor incididunt\nut labore et dolore magna aliqua.\nUt enim ad minim veniam,\nquis nostrud exercitation ullamco laboris nisi\nut aliquip ex ea commodo consequat.\nDuis aute irure dolor in reprehenderit in voluptate velit esse\ncillum dolore eu fugiat nulla pariatur.\nExcepteur sint occaecat cupidatat non proident,\nLorem ipsum dolor sit amet etwas,\nsunt in culpa qui officia deserunt mollit anim id est laborum"

out = replaceTokens(text, ["Lorem", "ut", "qui"], "<strong>$1</strong>", false)
out_phrases = replaceTokens(text, ["Lorem ipsum dolor sit amet", "Duis aute irure dolor in reprehenderit"], "<strong>$1</strong>", true)
document.getElementById("in_text").innerHTML = text.replace(/\n/g, '<br/>')
document.getElementById("out_text").innerHTML = out.replace(/\n/g, '<br/>')
document.getElementById("out_phrases").innerHTML = out_phrases.replace(/\n/g, '<br/>')
<div id="in_text"></div>
<hr>
<div id="out_text"></div>
<hr>
<div id="out_phrases"></div>

已添加jsfiddlesn-p 试用。

【问题讨论】:

  • 第二种情况的问题是短语的某些部分可能会进入下一行阻止匹配吗?代码 sn -p 似乎匹配第二种情况没有问题。
  • 您的第二个问题不清楚。你想做什么,预期的输出是什么?
  • [\n\s] 等于 \s
  • 试试new RegExp("^(" + word.replace(/([()'?*!"])/g, "\\$1") + ")$", "gim")
  • 请在您的问题中提供一个小提琴,就像您为第一个问题所做的那样,以便我们查看。

标签: javascript regex


【解决方案1】:

第一个问题似乎很清楚,将您的正则表达式字符串包装在 '\b'(字边界)中:

      text = text.replace(new RegExp("\\b(" + word + ")\\b", "gi"), expr);

这应该匹配“仅全词”。

第二个问题,在这里你可以检查它是文本的开头还是跟在一个点之后,或者是文本的结尾还是在它之后的一个点,像这样:

text = text.replace(new RegExp("(^|\\.\\s?|,\\s?)(" + word.replace(/([\(\)'?*!"])/g, "\\$1") + ")($|\\.|,)", "gi"), expr);

这个想法是它应该匹配SENTENCE,而不是line。一个句子要么从字符串的开头开始,要么在点或逗号之后,以点、逗号或字符串的结尾结束。

您不应使用“多行”选项。

编辑2

我已将我制作的群组更改为非捕获分组,因此它们不会对群组替换进行网格划分。现在是:

text = text.replace(new RegExp("(?:^|\\.\\s?)(" + word.replace(/([\(\)'?*!"])/g, "\\$1") + ")(?:\\.|,|$)", "gi"), expr);

现在它可以在 fiddle 上运行。

【讨论】:

  • 这是有道理的,但是如果我这样做text = text.replace(new RegExp("\b(" + word + ")\b", "gi"),如果您尝试修改后的 sn-p 它将不起作用...为什么?我得到了quialiquip
  • 需要转义:\\b
  • 是的,它在转义\\b 时工作正常。第二点是关于将令牌数组中传递的整行与文本中的行进行匹配,在某些情况下可以包含后者。我只想要完全匹配。
  • 您可以只链接到数百万个询问单词边界的问题之一,而不是复制内容,即Regex match entire words only
  • 嗯,我想回答这两个问题。
猜你喜欢
  • 2018-09-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-07
  • 2011-08-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多