我正在处理一个csv文件,里面有很多这样的行
"ATSMM","CCC","43 676 017111 / 017113"
"AERCM","XXX","54 320071 0900 / 0999"
目前使用的脚本能够识别“/”之前的数字和之后的数字。
my ($data, $start, $end) = m|(.* )(\d+) / (\d+)|;
上面的代码将 $ data 中的文本保存在“/”前面的数字之前 / $ start 之前的数字和 $ end 之后的数字。我对此进行排序的计划是将每个在$ start中的数字放在arrary1中,并将每个数字存储在array2中的$ end中。这是为了逐位分隔每个数字,这样我就可以列出一个范围。
我正在使用perl脚本,但欢迎任何其他选项。
谢谢!
答案 0 :(得分:2)
你想:
my ( @array1, @array2 );
while (...) {
my ($start, $end) = ...;
push @array1, $start;
push @array2, $end;
}
my @sorted_indexes = sort {
$array1[$a] <=> $array1[$b]
||
$array2[$a] <=> $array2[$b]
} 0..$#array1;
@array1 = @array1[@sorted_indexes];
@array2 = @array2[@sorted_indexes];
使用正确的CSV解析器:
use Text::CSV_XS qw( );
my ( @array1, @array2 );
my $csv = Text::CSV_XS->new({ binary => 1, auto_diag => 1 });
while (my $row = $csv->getline($fh)) {
my ($start, $end) = $row->[2] =~ /(\d+) \/ (\d+)/
or die("Bad data");
push @array1, $start;
push @array2, $end;
}
顺便说一下,很多人都避免使用并行数组,而更喜欢
my @array;
while (...) {
my ($start, $end) = ...;
push @array, [ $start, $end ];
}
@array = sort { $a->[0] <=> $b->[0] || $a->[1] <=> $b->[1] } @array;
答案 1 :(得分:0)
可能你正在寻找这个:
my ($start, undef, $end) = m{"((\d|\s)+) / (\d+)"};
更具体的是"
- s,因此它会找到csv行中的第三项。
它还使用{
和}
进行引用,因为|
用于指定模式中的替代项。
模式中有三个子匹配(三对()
,两个嵌套),但我们只使用第二个(嵌套的)将量词+
应用于替代(数字或空格),所以我们放弃该子匹配结果,并将其分配给左侧的undef
。
答案 2 :(得分:0)
您可以将该对收集为引用数组中的记录,并仍然使用记录中的字段对数组进行排序。它在语法上看起来很棘手,但很容易完成。基本上是push @ary, [ $2, $3 ];
然后,您可以按特定字段对记录进行排序:
use strict;
use warnings;
$/ = "\n";
my $line;
my @records = ();
while ( $line = <DATA> ) {
if ($line =~ m|(.* )(\d+) / (\d+)|) {
push @records, [$2, $3];
}
}
sub getSortedRecords {
my ( $field, $direction ) = @_;
return sort {
my($r1, $r2) = ($a, $b);
($r1, $r2) = ($b, $a) if $direction cmp 'descending';
$$r1[ $field ] <=> $$r2[ $field ];
} @records;
}
print "Ascending, fld 0\n";
for ( getSortedRecords( 0, 'ascending' ) ) {
print $$_[0], " / ", $$_[1], "\n";
}
print "\nAscending, fld 1\n";
for ( getSortedRecords( 1, 'ascending' ) ) {
print $$_[0], " / ", $$_[1], "\n";
}
print "\nDescending, fld 0\n";
for ( getSortedRecords( 0, 'descending' ) ) {
print $$_[0], " / ", $$_[1], "\n";
}
print "\nDescending, fld 1\n";
for ( getSortedRecords( 1, 'descending' ) ) {
print $$_[0], " / ", $$_[1], "\n";
}
__DATA__
"ATSMM","CCC","43 676 1 / 4"
"AERCM","XXX","54 320071 2 / 3"
"ATSMM","CCC","43 676 3 / 2"
"AERCM","XXX","54 320071 4 / 1"
Out&gt;&gt;
Ascending, fld 0
4 / 1
3 / 2
2 / 3
1 / 4
Ascending, fld 1
1 / 4
2 / 3
3 / 2
4 / 1
Descending, fld 0
1 / 4
2 / 3
3 / 2
4 / 1
Descending, fld 1
4 / 1
3 / 2
2 / 3
1 / 4