如何将变量放在数组中?

时间:2016-03-17 13:46:20

标签: regex perl

我正在处理一个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脚本,但欢迎任何其他选项。

谢谢!

3 个答案:

答案 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