如果前一个字符不是转义字符,如何使用分隔符分割字符串?

问题描述 投票:0回答:1

我必须解析一些代表 URL 和描述的数据。

格式为

https://stackoverflow.com/questions/ask, Ask
(
url, description
)。

由于 URL 中允许使用逗号,因此后端会用另一个逗号转义逗号(但仅限于 URL 部分)。

例如,以下输入字符串应解析为:

  • 输入:
    https://stackoverflow.com/questions/ask,, some weird path parts, Ask, with comma
  • 输出:
    • 网址:
      https://stackoverflow.com/questions/ask, some weird path parts
    • 描述:
      Ask, with comma

我正在努力寻找如何在第一次出现未转义的

, 
时分割字符串。

我的测试用例是

a,,b,, c, d, e,, f, ,, g
。我应该提取两个子字符串:
a,b, c
d, e,, f, ,, g
(描述部分不必转义逗号)。

我尝试使用正则表达式:

const input = 'a,, b,, c, d, e,, f';

const re = /(?<!,), /;

const parts = input.split(re);

console.log(parts, parts.length);

另一种尝试是使用非正则表达式解决方案:

const findUnescaped = (input: string): number => {
    let start = 0;

    while (true) {
        const i = input.indexOf(', ', start);

        if (i === -1) { // No separator at all
            return -1;
        }
        if (i === 0) { // Separator at begin of string
            return 0;
        }
        if (input[i - 1] !== ',') { // Found the separator without a preceding comma
            return i;
        }

        start = i + 2; // Looks further

    };
}

游乐场

但是,此函数无法正确处理

,,, 
(一个转义逗号和分隔符)。它将前面的逗号视为转义字符,即使它不是。

我该如何解决这个问题?

javascript regex
1个回答
1
投票

要将字符串在非“转义”逗号之前分成两部分,您可以使用

String.match()
模式,例如

const parts = input.match(/^([^,]*(?:,,[^,]*)*),\s*(.*)/)

请参阅 正则表达式演示

详情

  • ^
    - 字符串的开头
  • ([^,]*(?:,,[^,]*)*)
    - 第 1 组:零个或多个除逗号之外的字符,然后出现零个或多个
    ,,
    ,后跟零个或多个除逗号之外的字符
  • ,\s*
    - 逗号和零个或多个空白字符
  • (.*)
    - 第 2 组:字符串的其余部分。

如果您仅限于

String.split
,您的正则表达式将在 ECMAScript 2018+ JavaScript 环境中运行,您可以使用拆分方法

const parts = input.split(/(?<=(?<!,)(?:,,)*), (.*)/)

请参阅 此正则表达式演示

详情

  • (?<=(?<!,)(?:,,)*)
    - 积极的回顾,确保有
    • (?<!,)
      - 前面没有逗号的位置
    • (?:,,)*
      - 然后出现零次或多次偶数逗号
  • , 
    - 逗号和空格。
  • (.*)
    - 第 1 组:捕获字符串的其余部分。

演示:

const inputs = ['a,, b,, c, d, e,, f', 'a,, b,, c,,, d, e,, f'];
for (var input of inputs) {
  console.log(`== Testing: ${input}`)
  const [_, url, description] = input.match(/^([^,]*(?:,,[^,]*)*),\s*(.*)/)
  console.log(`URL: '${url}', Description: '${description}'.`)
  console.log(input.split(/(?<=(?<!,)(?:,,)*), (.*)/).filter(Boolean))
}

© www.soinside.com 2019 - 2024. All rights reserved.