如何在忽略引号内的任何逗号的情况下用逗号分隔? [复制]

Posted

技术标签:

【中文标题】如何在忽略引号内的任何逗号的情况下用逗号分隔? [复制]【英文标题】:How can I split by commas while ignoring any comma that's inside quotes? [duplicate] 【发布时间】:2019-12-25 20:24:41 【问题描述】:

我有一个 Typescript 文件,它接受一个 csv 文件并使用以下代码对其进行拆分:

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

我现在需要解决这个问题,以便引号内的任何逗号都不会导致拆分。例如,The,"quick, brown fox", jumped 应拆分为 Thequick, brown foxjumped,而不是同时拆分 quickbrown fox。这样做的正确方法是什么?

【问题讨论】:

这里是您正在寻找的答案:***.com/a/11457952/11945488 如果您需要解析 CSV,我强烈建议您使用 CSV 解析器。使用正则表达式很容易出现像您描述的那样的极端情况。 @Anton Bks 所以var cells = rowsTemp[i].split(/(".*?"|[^",\s]+)(?=\s*,|\s*$)/g); ?那是行不通的,它包括逗号。所以它将The, quick 拆分为The,quick 如果您选择该方法,我认为您需要使用 str.match,但是有多种解决方案。我建议检查所有这些,看看哪个最适合你的情况 @Christopher Peisert 该问题中的解决方案似乎都不适用于我正在尝试的内容 【参考方案1】:

更新:

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

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))

或者说得更漂亮:

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,
    ),
  )
;

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

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

    *?([^",]+?) *?,,这是一个没有", 的字符串,用空格包围,后跟," *?(.+?)" *?,,它是一个字符串,由一对引号和引号外不定数量的空格包围,后跟一个,( *?),,是不定数量的空格,后跟一个','。

因此,由这三个联合的非捕获组拆分基本上可以让我们找到答案。

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

    用分隔符分隔的字符串(正则表达式) 分隔符中的所有捕获组

在我们的例子中,分隔符填充了整个字符串,所以被分隔的字符串都是空字符串,除了最后一个想要的部分,因为没有,在它后面。因此结果数组应该是这样的:

    一个空字符串 三个字符串,代表匹配的第一个分隔符的三个捕获组 一个空字符串 三个字符串,表示匹配的第二个分隔符的三个捕获组 ... 一个空字符串 最后一个想要的部分,别管了

那么为什么要简单地在末尾添加一个, 以便我们可以得到一个完美的模式呢?这就是(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]],
    [],
  )

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

  .map(
    e => e.reduce(
      (a, b) => a !== undefined ? a : b, undefined,
    ),
  )

这就完成了解决方案。


我认为以下就足够了:

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

或者如果你不想要引号:

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

【讨论】:

这很接近,但我仍然遇到一些错误:它包含引号作为字符串的一部分,所以它返回"quick, brown fox",但应该返回quick, brown fox @Joe123,请查看我的更新。 让我想想第二个问题。 @Joe123,请查看此版本。 完美运行,感谢您的帮助!

以上是关于如何在忽略引号内的任何逗号的情况下用逗号分隔? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

GROOVY - 解析CSV:忽略双引号内的逗号

Java:拆分逗号分隔的字符串但忽略引号中的逗号

使用逗号拆分字符串,但忽略双引号内的逗号 - javascript

hive导入csv文件,字段中双引号内有逗号

numpy genfromtxt/pandas read_csv;忽略引号内的逗号

MySQL双引号加逗号,是啥分隔符