在忽略特殊字符的同时匹配和替换子字符串

Posted

技术标签:

【中文标题】在忽略特殊字符的同时匹配和替换子字符串【英文标题】:Match and replace a substring while ignoring special characters 【发布时间】:2016-12-21 19:43:18 【问题描述】:

我目前正在寻找一种将匹配文本转换为粗体 html 行的方法。我让它部分工作,除了特殊字符给我带来问题,因为我希望保持原始字符串,但不比较原始字符串。

例子:

给定原始字符串:

Taco John's is my favorite place to eat.

并且想要匹配:

is my 'favorite'

要得到想要的结果:

Taco John's <b>is my favorite</b> place to eat.

我目前绕过匹配字符串中多余引号的方法是替换它们

let regex = new RegExp('('+escapeRegexCharacters(matching_text.replace(/[^a-z 0-9]/gi,''))+')',"gi")
let html= full_text.replace(/[^a-z 0-9]/gi,'').replace(regex, "<b>$1</b>")></span>

这几乎可行,只是我丢失了所有标点符号:

Taco Johns <b>is my favorite</b> place to eat

有没有什么方法可以使用正则表达式或其他方法在匹配的短语周围添加标签,同时在匹配过程中忽略大小写和特殊字符?

更新 #1:

我好像不太清楚。我需要原始字符串的标点符号保留在最终结果的 html 中。而且我需要匹配的文本逻辑来忽略所有特殊字符和大写。所以is my favoriteis My favoriteis my 'favorite'都应该触发匹配。

【问题讨论】:

您提供的正则表达式的重点是删除任何不是“a-z”(空格)或数字的内容。因此只删除你的标点符号:regex101.com/r/M9HrNF/1 如果你成功转义正则表达式字符,为什么你需要删除非字母数字+空格? @DoTheDew 对,到目前为止,我正在删除标点符号以获得匹配,但我希望在最终结果中保留标点符号,但具有删除特殊字符的匹配逻辑。 【参考方案1】:

您可以在正则表达式中注入每个匹配字符之间的模式,该模式将跳过可能出现的任何特殊字符,而不是从正在搜索的字符串中删除特殊字符。这样您就可以构建一个可以直接应用于正在搜索的字符串的正则表达式,因此替换操作不会触及匹配项之外的特殊字符:

let escapeRegexCharacters = 
         s => s.replace(/[\-\[\]\/\\\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"),
    full_text = "Taco John's is My favorite place to eat.";
    matching_text = "is my 'favorite'";
    regex = new RegExp(matching_text.replace(/[^a-z\s\d]/gi, '')
                .split().map(escapeRegexCharacters).join('[^a-z\s\d]*'), "gi"),
    html = full_text.replace(regex, "<b>$&</b>");

console.log(html);

【讨论】:

这几乎完全正确。但是,当大小写不匹配时,它会失败。因此,如果matching_text 是“是我的'最喜欢的'”,它将不匹配,但我需要它。这就是我使用i 标志的原因,可以使用您的字符匹配方法吗? 改编:将gi 参数添加到主要new RegExp() 我明白了,我试图在错误的位置添加 gi 标志。谢谢!这非常聪明。【参考方案2】:

正则表达式在存在模式的情况下很有用,但是,在这种情况下,您可以直接匹配,因此,最好的方法是使用 String.prototype.replace

function wrap(source, part, tagName) 

  return source
    .replace(part, 
      `<$tagName>$part</$tagName>`
    )
  ;

至少,如果有一个模式,你应该编辑你的问题并提供它。

【讨论】:

这是真的,除了替换将精确匹配特殊字符。因此,"Taco John's is my favorite place to eat.".replace("is my 'favorite'", "ANYTHING") 将不起作用,因为 'part' 变量中有额外的单引号。【参考方案3】:

可以避免使用带有$&amp; replacement string 的捕获组,这意味着“整个匹配的子字符串”:

var phrase = "Taco John's is my favorite place to eat."
var matchingText = "is my favorite"

var re = new RegExp(escapeRegexCharacters(matchingText), "ig");
phrase.replace(re, "<b>$&</b>");

(代码基于 obarakon 的回答。)

【讨论】:

【参考方案4】:

概括地说,您可以使用is my /w+ 的正则表达式。您可以在替换函数中使用它,以便您可以通过 javascript 操作生成的文本:

var str = "Taco John's is my favorite place to eat.";
var html = str.replace(/is my \w*/, function (x) 
  return "<b>" + x + "</b>";
 );

console.log(html);

【讨论】:

【参考方案5】:

作为一个选项,对于单次出现的情况 - 使用 String.split 将 '###' 替换为 '@@@' 的示例:

let inputString = '1234###5678'
const chunks = inputString.split('###')
inputString = `$chunks[0]@@@$chunks[1]`

【讨论】:

以上是关于在忽略特殊字符的同时匹配和替换子字符串的主要内容,如果未能解决你的问题,请参考以下文章

python字符串中怎么忽略空格前面的数字

正则表达式

匹配两个特殊字符之间的子字符串,不包括字符

String的replace方法怎么转换带有特殊字符的子字符串?

正则表达式

忽略特殊 Unicode 字符的字符串比较