Python 解析字段中带有逗号的CSV文件

Python 解析字段中带有逗号的CSV文件,python,regex,perl,parsing,module,Python,Regex,Perl,Parsing,Module,我刚收到一个同事的文件,不知道如何解析: 输入: key,value1,"value2,hello" 期望输出: key,value2 Perl或Python是我理解的语言 谢谢,Bernardo这是,所以您可以使用CSV解析器 您没有指定使用哪种语言,但大多数都在类库中(例如,在.NET中)或作为外部组件(例如,在Apache Commons for Java中)提供了CSV解析器 如果您确实想重新发明轮子(我不推荐),那么算法非常简单: result = "", inQuotes = f

我刚收到一个同事的文件,不知道如何解析:

输入:

key,value1,"value2,hello"
期望输出:

key,value2
Perl或Python是我理解的语言

谢谢,Bernardo这是,所以您可以使用CSV解析器

您没有指定使用哪种语言,但大多数都在类库中(例如,在.NET中)或作为外部组件(例如,在Apache Commons for Java中)提供了CSV解析器

如果您确实想重新发明轮子(我不推荐),那么算法非常简单:

result = "", inQuotes = false
read next character
if end-of-line:
    if inQuotes:
        throw error (unmatched quotes)
    yield result
    return
else if character = '"':
    invert inQuotes
else if character = ',' and not inQuotes:
    yield result
    result = ""
else:
    result += character
这是,所以您可以只使用CSV解析器

您没有指定使用哪种语言,但大多数都在类库中(例如,在.NET中)或作为外部组件(例如,在Apache Commons for Java中)提供了CSV解析器

如果您确实想重新发明轮子(我不推荐),那么算法非常简单:

result = "", inQuotes = false
read next character
if end-of-line:
    if inQuotes:
        throw error (unmatched quotes)
    yield result
    return
else if character = '"':
    invert inQuotes
else if character = ',' and not inQuotes:
    yield result
    result = ""
else:
    result += character

使用正则表达式执行此操作的最佳方法:

[^,"]+|"(?:[^"]|"")+"


使用regex执行此操作的最佳方法:

[^,"]+|"(?:[^"]|"")+"


如果要使用正则表达式执行此任务,以下操作应该可以:

(\S+,)\d+,\"(\d+),\S+\"
(\S+,)
是选择第一个键(包括逗号)的第一个捕获组。后面是一些数字、逗号和引号
\d+,\”
。第二个捕获组
(\d+)
选择第二个值,后面是逗号、字符串和引号:
,\d+\“


但是,正如其他人所写,还有其他解决方案不涉及正则表达式。

如果您想使用正则表达式完成此任务,以下方法应该可以:

(\S+,)\d+,\"(\d+),\S+\"
(.*?)\,.*?\"(.*?)\,.*
(\S+,)
是选择第一个键(包括逗号)的第一个捕获组。后面是一些数字、逗号和引号
\d+,\”
。第二个捕获组
(\d+)
选择第二个值,后面是逗号、字符串和引号:
,\d+\“

但正如其他人已经写的,还有其他不涉及正则表达式的解决方案

(.*?)\,.*?\"(.*?)\,.*
你可以试试这个

见演示

你可以试试这个

见演示

标准Perl模块可用于处理CSV文件

#!/usr/bin/perl

use strict;
use warnings;

use Text::ParseWords;

while (<DATA>) {
  my @fields = parse_line(',', 0, $_);

  # Do something useful with the data in @fields
  print join ' | ', @fields;
}
__DATA__
key,value1,"value2,hello"
#/usr/bin/perl
严格使用;
使用警告;
使用Text::ParseWords;
而(){
my@fields=parse_行(',',0,$);
#对@fields中的数据执行一些有用的操作
打印联接“|”和@字段;
}
__资料__
键,值1,“值2,您好”
标准Perl模块可用于处理CSV文件

#!/usr/bin/perl

use strict;
use warnings;

use Text::ParseWords;

while (<DATA>) {
  my @fields = parse_line(',', 0, $_);

  # Do something useful with the data in @fields
  print join ' | ', @fields;
}
__DATA__
key,value1,"value2,hello"
#/usr/bin/perl
严格使用;
使用警告;
使用Text::ParseWords;
而(){
my@fields=parse_行(',',0,$);
#对@fields中的数据执行一些有用的操作
打印联接“|”和@字段;
}
__资料__
键,值1,“值2,您好”

到目前为止,您尝试了什么?你在用什么工具?看起来
awk
sed
可以很容易地做到这一点,您试过使用它们吗?到目前为止您试过什么?你在用什么工具?看起来
awk
sed
可以很容易做到这一点,您尝试过使用它们吗?根据CSV中的反斜杠没有特殊含义。引号内的引号将通过复制进行转义。这不考虑不匹配的引号,如果您有空值
test,test2
,也不会返回空的find。您可以将其更改为
[^,”]*|“(?:[^”]|“)*”
,但即使存在匹配项,也会提供空匹配项(regex perk)。谢谢@Heinzi,相应地进行了更改。根据反斜杠在CSV中没有特殊意义。引号内的引号将通过复制进行转义。这不考虑不匹配的引号,如果您有空值
test,test2
,也不会返回空的find。您可以将其更改为
[^,“]*|“(?:[^”]|“)*”
,但即使存在匹配项,也会提供空匹配项(regex perk)。谢谢@Heinzi,相应地进行了更改。