我知道这个问题是关于正则表达式的,但是你越是用正则表达式来做字符串拆分或子字符串提取的任务,你就越会注意到你的正则表达式的复杂性比你的字符串的复杂性增长得更快。首先,你必须避免按分隔符拆分字符串,如果分隔符在引号区域内,你只需使用一些几乎随机的正则表达式,它以某种方式工作;然后你需要考虑双引号区域,你修改你的正则表达式,使其增长3-4倍;依此类推。最终,你的正则表达式变成了一个如此复杂的东西,没有一个清醒的人会想要支持它。所以,尽管正则表达式的解决方案一开始看起来非常高级和优雅,但我最终停止使用它,并切换到了一个能够考虑引号区域的自定义函数。
interface IZoneToken {
begin: string;
end: string;
}
const ZONE_TOKENS: { [key: string]: IZoneToken } = {
SINGLE_QUOTES: { begin: '\'', end: '\'' },
DOUBLE_QUOTES: { begin: '\"', end: '\"' },
ROUND_BRACKETS: { begin: '(' , end: ')' }
};
function splitRespectingZones(input: string, delimiter: string, zone_tokens: IZoneToken[]): string[] {
let current_substring = '',
current_zone_token;
const substrings = [],
current_zone_tokens = [];
for (let i = 0; i < input.length; i++) {
const symbol = input[i];
if (symbol === delimiter && !current_zone_tokens.length) {
substrings.push(current_substring);
current_substring = '';
} else {
if (current_zone_token = zone_tokens.find(x => symbol === x.begin || symbol === x.end)) {
if (current_zone_token === current_zone_tokens.last()) {
if (current_zone_token.end === symbol) {
current_zone_tokens.pop()
} else {
current_zone_tokens.push(current_zone_token)
}
} else {
current_zone_tokens.push(current_zone_token)
}
current_zone_token = undefined;
}
current_substring += symbol;
}
}
if (current_substring) {
substrings.push(current_substring)
}
return substrings;
}
如你所见,你可以使用任意数量的自定义区域标记,无论是双引号、花括号还是其他括号。
splitRespectingZones(`some 'ran dom' "str ings" (fo r) ("example")`, ' ', [
{ begin: '\'', end: '\'' },
{ begin: '\"', end: '\"' },
{ begin: '(' , end: ')' }
])
// ['some', "'ran dom'", '"str ings"', '(fo r)', '("example")']
这段话有点啰嗦,但如果你需要修改这个函数,你会喜欢它的逻辑是多么简单直接。
问题中的案例示例:
splitRespectingZones('Time:"Last 7 Days" Time:"Last 30 Days"', ' ', [ { begin: '\"', end: '\"' } ])
foo:"bar none"
)识别为一个_单一_标记(并且也没有提到需要处理转义双引号的需求)。 - mklement0