Сортировка содержимого входного файла и запись выходного файла - PullRequest
0 голосов
/ 11 января 2019

Я хочу отсортировать содержимое текстового файла и сохранить его как другой текстовый файл (или перезаписать предыдущий). Я не особенно хорош в Perl, поэтому не могу понять, почему этот фрагмент кода не работает.

open(my $file, '>', $filename) or die $!;
print $file $string;

my @curOrd = qw( USD AUD BRL GBP CAD CNY DKK HKD INR IDR ILS JPY MXN NOK 
PHP PLN SGD SKK ZAR KRW SEK CHF TWD THB EUR MYR NZD SAR TRY RUB CZK AED CLP 
EGP MAD NGN OMR QAR );

my $curKnt = scalar @curOrd;
my $outfile = 'file1.txt';
my $infile = 'file2.txt';
open (OUTFILE, ">$outfile");

   foreach my $i (0..$curKnt) {
   open (INFILE, $infile);
   while(<INFILE>)
   {
        my @x= split(',', $_);
        print "x2 = $x[2]\n";
        print "cur_ord = $curOrd[$i]\n";
        if ($x[2] eq $curOrd[$i])  {
           print OUTFILE "$_";
        }
       @x=();
   }  # end of while

   close (INFILE);   

}  # end of foreach

close (OUTFILE);

Код должен сортировать каждую строку, сохраняя один и тот же формат. Однако, когда я запускаю его, я не получаю ошибок, но выходной файл нигде не найден.

входной_файл:

20181231,USD,AED,3.6736
20181231,USD,AUD,1.4179
20181231,USD,BRL,3.8817
20181231,USD,CAD,1.3632
20181231,USD,CHF,0.9842
20181231,USD,CLP,694.7432
20181231,USD,CNY,6.8787
20181231,USD,CZK,22.4985
20181231,USD,DKK,6.5252
20181231,USD,EGP,17.9426
20181231,USD,EUR,0.8738
20181231,USD,GBP,0.7853
20181231,USD,HKD,7.8322
20181231,USD,IDR,14483.0392
20181231,USD,ILS,3.7554
20181231,USD,INR,69.5662
20181231,USD,JPY,110.0258
20181231,USD,KRW,1114.7559
20181231,USD,MAD,9.6044
20181231,USD,MXN,19.6584
20181231,USD,MYR,4.1383
20181231,USD,NGN,365.4984
20181231,USD,NOK,8.6848
20181231,USD,NZD,1.4902
20181231,USD,OMR,0.3858
20181231,USD,PHP,52.5907
20181231,USD,PLN,3.7581
20181231,USD,QAR,3.6734
20181231,USD,RUB,69.5418
20181231,USD,SAR,3.7533
20181231,USD,SEK,8.9336
20181231,USD,SGD,1.3637
20181231,USD,SKK,26.3251
20181231,USD,THB,32.4579
20181231,USD,TRY,5.2938
20181231,USD,TWD,30.6034
20181231,USD,USD,1.0000
20181231,USD,ZAR,14.4104

Outputfile:

20181231,USD,USD,1.0000
20181231,USD,AUD,1.4220
20181231,USD,BRL,3.8828
20181231,USD,GBP,0.7880
20181231,USD,CAD,1.3643
20181231,USD,CNY,6.8782
20181231,USD,DKK,6.5295
20181231,USD,HKD,7.8316
20181231,USD,INR,69.7304
20181231,USD,IDR,14565.1115
20181231,USD,ILS,3.7693
20181231,USD,JPY,110.3364
20181231,USD,MXN,19.6687
20181231,USD,NOK,8.7288
20181231,USD,PHP,52.7242
20181231,USD,PLN,3.7660
20181231,USD,SGD,1.3674
20181231,USD,SKK,26.3387
20181231,USD,ZAR,14.4448
20181231,USD,KRW,1117.0950
20181231,USD,SEK,8.9869
20181231,USD,CHF,0.9846
20181231,USD,TWD,30.6213
20181231,USD,THB,32.6870
20181231,USD,EUR,0.8743
20181231,USD,MYR,4.1555
20181231,USD,NZD,1.4927
20181231,USD,SAR,3.7565
20181231,USD,TRY,5.2892
20181231,USD,RUB,69.4108
20181231,USD,CZK,22.5409
20181231,USD,AED,3.6728
20181231,USD,CLP,694.7031
20181231,USD,EGP,17.9262
20181231,USD,MAD,9.5636
20181231,USD,NGN,365.4074
20181231,USD,OMR,0.3860
20181231,USD,QAR,3.6423

Ответы [ 2 ]

0 голосов
/ 11 января 2019

Это работает, как и ожидалось, когда я проверяю это. Я могу только предположить, что существуют некоторые локальные проблемы, которые мешают вам либо открыть, либо записать в выходной файл. Вы увидите, что это за проблема, если вы проверили возвращаемое значение из open() и предприняли соответствующее действие.

Я взял на себя смелость ужесточить часть вашего кода:

my @curOrd = qw( USD AUD BRL GBP CAD CNY DKK HKD INR IDR ILS JPY MXN NOK
                 PHP PLN SGD SKK ZAR KRW SEK CHF TWD THB EUR MYR NZD SAR
                 TRY RUB CZK AED CLP EGP MAD NGN OMR QAR );

my $outfile = 'file1.txt';
my $infile = 'file2.txt';
open (my $out_fh, '>', $outfile)
  or die "Cannot open $outfile: $!";

# Iterating over the values in a list is usually
# better than iterating over the indexes.
foreach my $cur (@curOrd) {
  open ($in_fh, '<', $infile)
    or die "Cannot open $infile: $!";

  while(<$in_fh>) {
    my @x = split(/,/);
    print "x2 = $x[2]\n";
    print "cur_ord = $cur\n";

    if ($x[2] eq $cur)  {
      print $out_fh $_;
    }
  }  # end of while

  close ($in_fh);
}  # end of foreach

close ($out_fh);

Обновление: Открытие и закрытие входного файла столько раз очень неэффективно. Эта версия открывает его один раз, разбивает данные на двумерный массив и затем сортирует их.

my @curOrd = qw( USD AUD BRL GBP CAD CNY DKK HKD INR IDR ILS JPY MXN NOK
                 PHP PLN SGD SKK ZAR KRW SEK CHF TWD THB EUR MYR NZD SAR 
                 TRY RUB CZK AED CLP EGP MAD NGN OMR QAR );

# Build a look-up table mapping currencies to their
# sort position
my $i = 0;
my %cur_lookup = map { $_ => $i++ } @curOrd;

my $outfile = 'file1.txt';
my $infile = 'file2.txt';
open (my $out_fh, '>', $outfile)
  or die "Cannot open $outfile: $!";

open(my $in_fh, '<', $infile)
  or die "Cannot open $infile: $!";

my @in_data = map { [ split /,/ ] } <$in_fh>;

print $out_fh
  map { join ',', @$_ }
  sort { $cur_lookup{$a->[2]} <=> $cur_lookup{$b->[2]} } @in_data;

close ($in_fh);
close ($out_fh);
0 голосов
/ 11 января 2019

Причина, по которой ваш код не работает, заключается в том, что вы пытаетесь прочитать значение массива вне диапазона. Сценарий умирает в этой точке. Чтобы исправить это, добавьте строку $ curKnt -;

my $curKnt = scalar @curOrd;
$curKnt--;

Еще одна проблема с вашим сценарием, он открывает и закрывает $ infile более 30 раз, что не очень хорошая идея. Я думаю, что вы должны переписать свой код, чтобы прочитать $ infile один раз в массив или хэш, а затем обработать этот массив или хэш. Я бы написал так:

use strict;
use warnings;

my @curOrd = qw( USD AUD BRL GBP CAD CNY DKK HKD INR IDR ILS JPY MXN NOK PHP PLN SGD SKK ZAR KRW SEK CHF TWD THB EUR MYR NZD SAR TRY RUB CZK AED CLP EGP MAD NGN OMR QAR );

my %data;
my $infile  = 'file2.txt';
my $outfile = 'file1.txt';

open (my $in, "<", $infile) || die "can't open $infile file"; 
while (my $line = <$in>) {
    push(@{$data{(split ',', $line)[2]}}, $line);
}
close $in;

open (my $out, ">", $outfile) || die "can't open $outfile file"; 
foreach my $curr (@curOrd) {
    foreach my $line (@{$data{$curr}}) {
        print $out $line;
    }
}
close $out;
...