如何在忽略引号内的任何逗号的情况下用逗号分隔? [复制]
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
应拆分为 The
、quick, brown fox
和 jumped
,而不是同时拆分 quick
和 brown 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,请查看此版本。
完美运行,感谢您的帮助!以上是关于如何在忽略引号内的任何逗号的情况下用逗号分隔? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
使用逗号拆分字符串,但忽略双引号内的逗号 - javascript