匹配并替换引号中没有的单词(字符串包含转义的引号)

时间:2019-01-20 07:58:47

标签: javascript regex

如果给定字符串中的某个特定单词出现在引号中,则该单词如何替换为另一个。请注意,输入字符串很可能包含转义的引号。这个词本身将不包含任何引号。

[编辑:最初的措辞是-“输入字符串中肯定会包含转义的引号”。后来我意识到这不是“绝对”,而是“最有可能”]。

示例:用BAR代替FOO

输入:FOO "FOO" 'FOO' " 1 + FOO + 2 " ABCFOOXYZ " str1\"FOO\"str3'FOO'\'\'" ' str1\'FOOstr3"FOO"\"\"' \"FOO\"

输出:BAR "FOO" 'FOO' " 1 + FOO + 2 " ABCBARXYZ " str1\"FOO\"str3'FOO'\'\'" ' str1\'FOOstr3"FOO"\"\"' \"BAR\"

请注意,最后一次出现的FOO不在引号内,引号本身已被转义。因此,它被BAR取代。

我正在寻找JavaScript中的正则表达式。

说明-输入字符串将包含单引号和双引号,两者都可能转义。仅在根本不使用单引号的情况下(单引号或双引号均不使用),才应替换该词。

编辑:

我尝试了什么:我能够获得所有不应该更换的FOO ([“'])(?:(?=(\?))\ 2。)*?\ 1 上面将匹配所有引用的字符串。应该将它们排除在替代范围之外。

我不是regexp专业人士,我已经尝试了很多。

1 个答案:

答案 0 :(得分:0)

您可以通过使用捕获组,字符类和反向引用(['"])来匹配单引号或双引号之间的所有内容,以便相同的开始引号匹配相同的结束引号。然后使用轮流捕获第二个捕获组中的FOO

方法replace具有回调函数,您可以在其中访问完全匹配项作为第一个参数,而捕获组作为其余参数。在这里,您可以测试第二组的价值。如果是FOO,则返回BAR

如果不是,请返回完整匹配。

(?:\s|^)(['"])(?:\1|.*?[^\\]\1)|(FOO)

说明

  • (?:\s|^)字符串或空白字符的开头
  • (['"])在捕获组中匹配'"
  • (?:非捕获组
    • \1向第一个捕获组的反向引用
    • |
    • .*?[^\\]\1匹配除第1组以外的新行非贪心,后跟非反斜杠和反向引用之外的所有字符
  • )关闭非捕获组
  • |
  • (FOO)捕获包含FOO的第2组

Regex demo

let pattern = /(?:\s|^)(['"])(?:\1|.*?[^\\]\1)|(FOO)/g;
let str = `FOO "FOO" 'FOO' "    1 + FOO + 2 " ABCFOOXYZ "  str1\\"FOO\\"str3'FOO'\\'\\'" '  str1\\'FOOstr3"FOO"\\"\\"' \\"FOO\\"`;
let res = str.replace(pattern, function(m, _, g2) {
  return g2 === "FOO" ? "BAR" : m;
});
console.log(res);