处理不带双引号的 CSV 文件

Processing CSV file without double quotes

换句话说,我正在寻找一种方法来忽略其中一个字段中的“,”。

该字段应被视为一个单独的字段,即使它包含一个逗号。

示例:

Round,Winner,place,prize
1,xyz,1,,500

如果我用 dict reader 阅读这个 ,500 打印为 </code> 因为 <code>500 被认为是另一个字段。,这在我阅读时很有意义文件以逗号分隔,所以我真的不能抱怨,而是想办法解决。

reader = csv.reader(f, delimiter=',', quotechar='"')

我的来源没有用双引号引起来,所以我不能通过包含引号字符串来忽略它。

还有其他方法可以处理这种情况吗?可能类似于定义这些美元字段并使其忽略该字段的逗号?或者尝试在该字段周围插入引号?

如果不是 Python,可以使用 shell 脚本或 Perl 来完成吗?

如果额外的 , 在存在时总是成为最后一个字段的一部分,您可以对其使用 Bash 读取循环:

#!/bin/bash

while IFS=, read -r f1 f2 f3 f4; do
   # f4 => has everything after f3, including extra commas as in ,500
   # do your processing
   printf "f1=[$f1] f2=[$f2] f3=$[f3] f4=[$f4]\n"
done < input.txt

输入:

1,xyz,1,,500
2,abc,3,0

输出:

f1=[1] f2=[xyz] f3=1 f4=[,500]
f1=[2] f2=[abc] f3=3 f4=[0]

也许pre-process数据把所有的钱都用引号括起来,然后正常处理

$line =~ s/( $\d+ (?:,\d{3})* (?:\.\d{2})? )/""/gx;

该模式匹配 $ 之后的数字,可选地后跟 ,nnn and/or 的任意倍数 .nn。它还包含 .220,我认为这有利于一致性。如果需要,限制匹配的内容,例如 ($\d{1,3},\d{3})。使用分数美分删除 {2}。这并未涵盖所有可能的 edge/broken 个案例。

/g 修饰符使其替换行中的所有此类内容,并且 /x 允许空格以供阅读。

你可以像 one-liner

perl -pe 's/($\d+(?:,\d{3})*(?:\.\d{2})?)/""/g' input.csv  > changed.csv

添加 -i 开关以覆盖输入 ("in-place"),或 -i.bak 也保留备份。


如果您预计需要进一步调整,或者为了更好地记录这一点,请将其放入脚本中

use warnings;
use strict;

my $file = '...';
my $fout = '...';

open my $fh,     '<', $file or die "Can't open $file: $!";
open my $fh_out, '>', $fout or die "Can't open $fout for writing: $!";

while (my $line = <$fh>) {
    $line =~ s/( $\d+ (?:,\d{3})* (?:\.\d{2})? )/""/gx;
    print fh_out $line;
}

close $fh;
close $fh_out;