替换不在多个可能的多字符机箱之一内的字符串

时间:2019-01-27 06:42:41

标签: javascript regex

我想用JavaScript的.replace来解析一个字符串, except ,如果它位于多对定界符之间。哪种方法最简单,并且希望最通用和/或最有效?

我尝试在正则表达式中交替选择左定界符和右定界符;在.replace中使用回调参数在地图对象中查找每个匹配项的两个捕获的定界符;并做出相应的响应,但是此解决方案并不完全有效

在这种特殊情况下,我想替换++的实例,然后立即替换至少一个非加号字符,然后立即替换++,仅用大写的文字替换-除非实例在@<>@@@@@之间,但不一定紧随在它们之后。

var options = {
    '@<': ['>@', 5, 2],
    '@@': ['@@', 2, 2]
},
possiblyParse = str => str.replace(/(@<|@@|^).+?(>@|@@|$)/g, (a, b, c) =>
    options.hasOwnProperty(b) && options[b][0] == c ?
    a.slice(options[b][1], a.length - options[b][2]) : // If string suitably enclosed, return it without delimiters
    a.replace(/\+\+([^\+]+)\+\+/g, (a, b) => b.toUpperCase())); // Otherwise, do something, keeping delimiter(s) if any
console.log(possiblyParse('input'));

此代码会产生这些可接受的结果……

console.log(possiblyParse('++abc++'))); // ABC
console.log(possiblyParse('@<++abc++>@')); // ++abc++
console.log(possiblyParse('@@++abc++@@')); // ++abc++
console.log(possiblyParse('@<++abc++@@')); // @<ABC@@
console.log(possiblyParse('@@++abc++>@')); // @@ABC>@
console.log(possiblyParse('@<++abc++')); // @<ABC
console.log(possiblyParse('++abc++@@')); // ABC@@

…并在此处失败:

console.log(possiblyParse('z@<@++abc++>@')) // z@<ABC>@, should be z++abc++
console.log(possiblyParse('++abc++ @<@++abc++>@')) // ABC @<ABC>@, should be ABC ++abc++

我怀疑我的正则表达式/(@<|@@|^).+?(>@|@@|$)/g存在问题,我认为它与@<@@或输入的开头匹配,然后懒惰地匹配至少一个字符,然后匹配{ {1}},>@或输入的结尾。您能解决这个问题吗?

1 个答案:

答案 0 :(得分:0)

在收到其他用户的答案之前,我已经找到了以下解决方案,但是,如果您有更好的答案,请贡献它。

我的解决方案只是在可能的定界符中对每个字符串进行编码,以使结果不包含++对,然后进行大写,然后对所有编码后的字符串进行解码。

var encodeWithOrDecode = (x, y) => y ?
    (a, b) => x + b.replace(/./g, // Callback to replace each character to be encoded with...
        e => '<' + e.charCodeAt().toString(36) + '<') + y : // ... its number, in base 36, between '<' and '<'
    (c, d) => d.replace(/<(\w+)</g, (a, b) => String.fromCharCode(parseInt(b, 36))); // Callback to decode each portion of string to be decoded
console.log('++just got up++|@&lt;feeling down>@|@@in the dumps@@'
    .replace(/@&lt;(.+?)>@/g, encodeWithOrDecode('@&lt;', '>@')).replace(/@@(.+?)@@/g, encodeWithOrDecode('@@', '@@')) // Encodes text to be left raw
    .replace(/\+\+([^\+]+)\+\+/g, (a, b) => b.toUpperCase()) // Capitalises only text to be parsed
    .replace(/@&lt;(.+?)>@/g, encodeWithOrDecode()).replace(/@@(.+?)@@/g, encodeWithOrDecode())); // Decodes text to be left raw

说明

/@&lt;(.+?)>@/g/@@(.+?)@@/g将匹配相关分隔符的所有实例,且两者之间都包含文本。

  • 左定界符(分别为@&lt;@@)在字面上匹配
  • 捕获组至少匹配一次非行终止字符
  • 右定界符(分别为>@@@)在字面上匹配

.replace中使用了以上两个正则表达式的情况下,encodeWithOrDecode返回的同一函数中的回调将匹配项作为参数。第二个此类参数是捕获组中的参数,并进行编码或解码。