处理没有双引号的CSV文件

时间:2017-01-27 18:18:36

标签: python perl shell csv delimiter

换句话说,我正在寻找一种方法来忽略","在其中一个领域。

即使字段包含逗号,也应将该字段视为一个字段。

示例:

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

如果我用dict阅读器阅读此内容$4,500打印为$4因为500被认为是另一个字段。这是有意义的,因为我正在以逗号分隔的方式读取文件,所以我不能抱怨,但试着想办法解决。

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

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

还有其他方法可以处理这种情况吗?可能类似于定义这些美元字段并使其忽略该字段的逗号?或者试着在这个领域附近引用?

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

2 个答案:

答案 0 :(得分:8)

也许预先处理数据以将所有钱包装在引号中,然后正常处理

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

该模式与$后面的数字匹配,可选地后跟,nnn和/或.nn的任意倍数。它还包含$4.22以及$100,我认为这对于一致性很有帮助。根据需要限制匹配的内容,例如(\$\d{1,3},\d{3})。使用小数美分删除{2}。这并不包括所有可能的边缘/破损情况。

/g修饰符使其替换行中的所有内容,而/x允许空格可读。

你可以做一个单行

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

添加-i开关以覆盖输入(" 就地")或-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})? )/"$1"/gx;
    print fh_out $line;
}

close $fh;
close $fh_out;

答案 1 :(得分:1)

如果额外的,总是存在于最后一个字段的一部分,你可以使用Bash读取循环:

#!/bin/bash

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

输入:

1,xyz,1,$4,500
2,abc,3,$400

输出:

f1=[1] f2=[xyz] f3=1 f4=[$4,500]
f1=[2] f2=[abc] f3=3 f4=[$400]