我想用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}},>@
或输入的结尾。您能解决这个问题吗?
答案 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++|@<feeling down>@|@@in the dumps@@'
.replace(/@<(.+?)>@/g, encodeWithOrDecode('@<', '>@')).replace(/@@(.+?)@@/g, encodeWithOrDecode('@@', '@@')) // Encodes text to be left raw
.replace(/\+\+([^\+]+)\+\+/g, (a, b) => b.toUpperCase()) // Capitalises only text to be parsed
.replace(/@<(.+?)>@/g, encodeWithOrDecode()).replace(/@@(.+?)@@/g, encodeWithOrDecode())); // Decodes text to be left raw
说明
/@<(.+?)>@/g
或/@@(.+?)@@/g
将匹配相关分隔符的所有实例,且两者之间都包含文本。
@<
或@@
)在字面上匹配>@
或@@
)在字面上匹配在.replace
中使用了以上两个正则表达式的情况下,encodeWithOrDecode
返回的同一函数中的回调将匹配项作为参数。第二个此类参数是捕获组中的参数,并进行编码或解码。