我正在尝试做类似的事情,但无法让它工作。
How to split a comma separated String while ignoring escaped commas?
我试图弄明白,但似乎做对了。
我想在 :
上拆分字符串,但不是转义的字符串 \\:
(我的转义字符是双斜杠)
给定:dtet:du\\,eduh ei\\:di:e,j
预期结果:["dtet"] ["du\\,eduh ei\\:di][e,j"]
正则表达式链接: https://regex101.com/r/12j6er/1/
最佳答案
请参阅下面名为 splitOnNonEscapedDelimeter()
的函数,它接受要拆分的 string
和要拆分的 delimeter
,在此大小写是 :
。用法在函数 onChange()
中。
Note that you must escape the
delimeter
you pass tosplitOnNonEscapedDelimeter()
, so that it is not interpreted as a special character in the regular expression.
function nonEscapedDelimeter(delimeter) {
return new RegExp(String.raw`[^${delimeter}]*?(?:\\\\${delimeter}[^${delimeter}]*?)*(?:${delimeter}|$)`, 'g')
}
function nonEscapedDelimeterAtEnd(delimeter) {
return new RegExp(String.raw`([^\\].|.[^\\]|^.?)${delimeter}$`)
}
function splitOnNonEscapedDelimeter(string, delimeter) {
const reMatch = nonEscapedDelimeter(delimeter)
const reReplace = nonEscapedDelimeterAtEnd(delimeter)
return string.match(reMatch).slice(0, -1).map(section => {
return section.replace(reReplace, '$1')
})
}
function onChange() {
console.log(splitOnNonEscapedDelimeter(i.value, ':'))
}
i.addEventListener('change', onChange)
onChange()
<textarea id=i>dtet:du\\,eduh ei\\:di:e,j</textarea>
要求
此解决方案利用了 ES2015 功能 String.raw()
和 template literals为方便起见,尽管这些不是必需的。请参阅上面的相关文档以了解这些如何工作和使用 a polyfill such as this如果您的目标平台不支持这些功能。
说明
new RegExp(String.raw`[^${delimeter}]*?(?:\\\\${delimeter}[^${delimeter}]*?)*(?:${delimeter}|$)`, 'g')
nonEscapedDelimeter()
函数创建了一个正则表达式,几乎可以完成所需的工作,除了一些需要通过一些后期处理来纠正的怪癖。
string.match(reMatch)
正则表达式,用于String#match()
, 将字符串拆分为以非转义 delimeter
结尾或以字符串结尾的部分。这也有在字符串末尾匹配 0 宽度部分的副作用,因此我们需要
.slice(0, -1)
在后处理中删除该匹配项。
new RegExp(String.raw`([^\\].|.[^\\]|^.?)${delimeter}$`)
...
.map(section => {
return section.replace(reReplace, '')
})
由于每个部分现在都以 delimeter
结束,除了最后一个(在字符串末尾结束),我们需要 .map()
匹配数组并删除 非转义 delimeter
(这就是为什么 nonEscapedDelimeterAtEnd()
如此复杂),如果它存在的话。
关于JavaScript 在 char 上拆分但忽略双重转义字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45131764/