【发布时间】:2014-07-09 17:06:13
【问题描述】:
我想编写一个 Perl 脚本:
- 定期监控输入 CSV 文件的文件目录
- 在文件检测时,打开、读取和合并第二个字段/列具有相同值的多行
- 将更新的 CSV 文件写入新目录,最后,
- 删除输入文件。
例如,我有一个包含如下信息的 CSV 文件:
"101","5555555555","DOE, JOHN "," DOE, JOHN, your trip
tomorrow from, 123 Anywhere St Apt #A, to, 100 ELSEWHERE RD APT E, is
scheduled for pickup between, 1:00 PM, and 1:30 PM"
"102","5555555555","DOE, JOHN "," DOE, JOHN, your trip
tomorrow from, 100 ELSEWHERE RD APT E, to, 123 Anywhere St Apt #A, is
scheduled for pickup between, 9:00 PM, and 9:30 PM"
我想让脚本读取、解析和检测第二个字段(“5555555555”)的重复值,然后创建一个新的 CSV 文件,将上述记录合并为一条记录:
"101","5555555555","DOE, JOHN "," DOE, JOHN, your trip
tomorrow from, 123 Anywhere St Apt #A, to, 100 ELSEWHERE RD APT E, is
scheduled for pickup between, 1:00 PM, and 1:30 PM AND your trip
tomorrow from, 100 ELSEWHERE RD APT E, to, 123 Anywhere St Apt #A, is
scheduled for pickup between, 9:00 PM, and 9:30 PM"
我当前的 Perl 代码成功地检测、读取和解析文件,但是,我不知道如何检测重复项和合并行。
#!
use strict;
use warnings;
use File::Find;
use Text::CSV;
$| = 1;
use constant {
#Check for CSV files only
SUFFIX_LIST => qr/\.(csv)$/,
DIR_TO_CHECK => "/Users/Me/Desktop/INBOUND/",
};
my @file_list;
while (1) {
#Recursively search the input directory for CSV files
find ( sub {
return unless -f;
return unless $_ =~ SUFFIX_LIST;
#Make sure all of the files in the file list array are unique
if(!(grep(/^$_$/, @file_list))) {
push @file_list, $File::Find::name;
}
}, DIR_TO_CHECK
);
#If .csv files are found...
if (scalar(@file_list) > 0) {
print "\nNew Item in Directory\n";
parseFile($file_list[0]);
#Delete input file
unlink $file_list[0];
print "Deleted File\n";
#Remove the file from the file list
shift @file_list;
} else {
print "No New Item\n";
}
sleep 5;
}
#Subroutine to parse and compare the csv file
sub parseFile() {
my $csv = Text::CSV->new({ sep_char => ',',
always_quote => 1,
quote_char => '"',
escape_char => '"',
binary => 1,
auto_diag => 1});
#Get the file that was passed to the function
my $file = $_[0] or die "CSV file not passed in subroutine\n";
#Open file for reading
open(my $data, '<', $file) or die "Could not open '$file' $!\n";
while (my $line = <$data>) {
print $line;
if ($csv->parse($line)) {
my @fields = $csv->fields();
} else {
#warn "Line could not be parsed: $line\n";
Text::CSV->error_input();
}
}
close $data;
}
我认为我正在寻找的功能是错误的,因为我怀疑我需要将文件作为一个整体读入内存,而不是逐行读取。请帮忙,谢谢。
【问题讨论】:
-
第一列好像没有用于重复检测,但是第三列呢?另外,行需要按特定顺序合并吗?
-
@ThisSuitIsBlackNot 第三列也不用于重复检测。理想情况下,将按照第一列指定的顺序合并行。谢谢
-
因此,如果由于某种原因,您有一行
1,42,jack,foo后跟2,42,jill,bar,那么合并后的结果是否会在第三列中包含jack或jill? -
@ThisSuitIsBlackNot Good question...至少现在,我会选择
jack。因此,更新的行是1,42,jack,foo AND bar