我有像
这样的数据"scott
E -45 COLLEGE LANE
BENGALI MARKET
xyz -785698."
"Tomm
D.No: 4318/3,Ansari Road, Dariya Gunj,
xbc - 289235."
我编写了一个Perl程序来提取名称,即
open(my$Fh, '<', 'printable address.txt') or die "!S";
open(my$F, '>', 'names.csv') or die "!S";
while (my@line =<$Fh> ) {
for(my$i =0;$i<=13655;$i++){
if ($line[$i]=~/^"/) {
print $F $line[$i];
}
}
}
它工作正常,它精确地提取名称。现在我的目标是提取类似
的地址BENGALI MARKET
xyz -785698."
D.No: 4318/3,Ansari Road, Dariya Gunj,
xbc - 289235."
在CSV文件中。怎么做请告诉我
答案 0 :(得分:0)
原始问题存在很多缺陷。在提出任何改进之前应该解决这些问题:
use strict;
和use warnings;
。or die "!S"
语句已损坏。错误代码实际上在$!
中。但是,您可以通过use autodie;
$Fh
和$F
没有说明这些内容。至少将它们标记为$infh
和$outfh
。while (my @line = <$Fh>) {
存在缺陷,因为它可以缩减为my @line = <$Fh>;
。因为你要在列表上下文中读取readline,它会使整个文件出现问题,然后它会退出下一个循环。相反,将它分配给标量,你甚至不需要下一个for循环。@line
,那么您对for(my$i =0;$i<=13655;$i++){
的使用也存在缺陷。您应该迭代到@line
的最后一个索引,即$#line
。 if ($line[$i]=~/^"/) {
也存在缺陷,因为您将引号字符"
留在您要匹配的名称的开头。而是添加一个捕获组来提取名称。根据建议的更改,代码将缩减为:
use strict;
use warnings;
use autodie;
open my $infh, '<', 'printable address.txt';
open my $outfh, '>', 'names.csv';
while (my $line = <$infh>) {
if ($line =~ /^"(.*)/) {
print $outfh "$1\n";
}
}
现在,如果您还想隔离地址,可以使用与名称相似的方法。我将假设您可能希望在变量中构建整个地址,以便您可以执行更复杂的操作,而不是将它们盲目地放在文件中。但是,现在镜像文件设置:
use strict;
use warnings;
use autodie;
open my $infh, '<', 'printable address.txt';
open my $namefh, '>', 'names.csv';
open my $addressfh, '>', 'address.dat';
my $address = '';
while (my $line = <$infh>) {
if ($line =~ /^"(.*)/) {
print $namefh "$1\n";
} elsif ($line =~ /(.*)"$/) {
$address .= $1;
print $addressfh "$address\n";
$address = '';
} else {
$address .= $line;
}
}
最终,无论您想要使用什么数据,最佳解决方案都可能是使用Text::CSV
将其输出到真实的CSV文件。这样就可以非常轻松地将其导入到电子表格或其他系统中,您无需再次解析它。
use strict;
use warnings;
use autodie;
use Text::CSV;
my $csv = Text::CSV->new ( { binary => 1, eol => "\n" } )
or die "Cannot use CSV: ".Text::CSV->error_diag ();
open my $infh, '<', 'printable address.txt';
open my $outfh, '>', 'address.csv';
my @data;
while (my $line = <$infh>) {
# Name Field
if ($line =~ /^"(.*)/) {
@data = ($1, '');
# End of Address
} elsif ($line =~ /(.*)"$/) {
$data[1] .= $1;
$csv->print($outfh, \@data);
# Address lines
} else {
$data[1] .= $line;
}
}