如何用逗号分隔,同时忽略引号内的任何逗号?

Joe*_*123 0 regex csv typescript

我有一个 Typescript 文件,它采用 csv 文件并使用以下代码拆分它:

var cells = rows[i].split(",");

我现在需要解决这个问题,以便引号内的任何逗号都不会导致拆分。例如,The,"quick, brown fox", jumped应该拆分为The, quick, brown fox, 和jumped而不是也拆分quickbrown fox。执行此操作的正确方法是什么?

Col*_*iot 5

更新:

我认为一行的最终版本应该是:

var cells = (rows[i] + ',').split(/(?: *?([^",]+?) *?,|" *?(.+?)" *?,|( *?),)/).slice(1).reduce((a, b) => (a.length > 0 && a[a.length - 1].length < 4) ? [...a.slice(0, a.length - 1), [...a[a.length - 1], b]] : [...a, [b]], []).map(e => e.reduce((a, b) => a !== undefined ? a : b, undefined))
Run Code Online (Sandbox Code Playgroud)

或者说得更漂亮一点:

var cells = (rows[i] + ',')
  .split(/(?: *?([^",]+?) *?,|" *?(.+?)" *?,|( *?),)/)
  .slice(1)
  .reduce(
    (a, b) => (a.length > 0 && a[a.length - 1].length < 4)
      ? [...a.slice(0, a.length - 1), [...a[a.length - 1], b]]
      : [...a, [b]],
    [],
  )
  .map(
    e => e.reduce(
      (a, b) => a !== undefined ? a : b, undefined,
    ),
  )
;
Run Code Online (Sandbox Code Playgroud)

这是相当长的,但看起来仍然纯粹是功能性的。让我解释一下:

首先,正则表达式部分。基本上,您想要的细分可能有 3 种可能性:

  1. *?([^",]+?) *?,",它是一个没有空格或被空格包围的字符串,,后跟,.
  2. " *?(.+?)" *?,,它是一个字符串,由一对引号和引号之外的无限数量的空格包围,后跟,.
  3. ( *?),,它是不定数量的空格,后跟“,”。

因此,通过这三个联合体的非捕获组的分裂基本上可以让我们得到答案。

回想一下,当使用正则表达式进行拆分时,结果数组包含:

  1. 由分隔符(正则表达式)分隔的字符串
  2. 分隔符中的所有捕获组

在我们的例子中,分隔符填充了整个字符串,因此分隔的字符串都是空字符串,除了最后一个所需的部分,该部分被省略,因为后面没有,后面的部分。因此得到的数组应该是这样的:

  1. 空字符串
  2. 三个字符串,代表匹配的第一个分隔符的三个捕获组
  3. 空字符串
  4. 三个字符串,代表第二个分隔符匹配的三个捕获组
  5. ...
  6. 空字符串
  7. 最后想要的部分,单独留下

那么为什么只是,在末尾添加 a 就能得到完美的图案呢?事情就是这样(rows[i] + ',')发生的。

在这种情况下,生成的数组成为由空字符串分隔的捕获组。删除第一个空字符串,它们将以 4 个一组的形式出现,如 [ 第一个捕获组,第二个捕获组,第三个捕获组,空字符串 ]。

reduce块的作用是将它们精确地分为 4 组:

  .reduce(
    (a, b) => (a.length > 0 && a[a.length - 1].length < 4)
      ? [...a.slice(0, a.length - 1), [...a[a.length - 1], b]]
      : [...a, [b]],
    [],
  )
Run Code Online (Sandbox Code Playgroud)

最后,找到每个组中的第一个非undefined元素(不匹配的捕获组将显示为undefined。我们的三个模式是互斥的,因为它们中的任何两个都不能同时匹配。因此每个组中恰好有 1 个这样的元素),它们是正是所需的部分:

  .map(
    e => e.reduce(
      (a, b) => a !== undefined ? a : b, undefined,
    ),
  )
Run Code Online (Sandbox Code Playgroud)

这样就完成了解决方案。


我认为以下内容应该足够了:

var cells = rows[i].split(/([^",]+?|".+?") *, */).filter(e => e)
Run Code Online (Sandbox Code Playgroud)

或者如果您不想要引号:

var cells = rows[i].split(/(?:([^",]+?)|"(.+?)") *, */).filter(e => e)
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

4133 次

最近记录:

6 年,3 月 前