Управляемый данными Perl-скрипт - PullRequest
0 голосов
/ 24 июня 2019

Я хочу перечислить папку n файла в каталоге.Вот список файлов в этом каталоге.

Output1.sv
Output2.sv
Folder1
Folder2
file_a
file_b
file_c.sv

Но некоторые из них, я не хочу, чтобы он был в списке.Список не включенных файлов я перечисляю в input.txt, как показано ниже.Примечание: некоторые из них являются файловыми, а некоторые - папками

NOT_INCLUDED=file_a
NOT_INCLUDED=file_b
NOT_INCLUDED=file_c.sv

Вот код.

#!/usr/intel/perl

use strict;
use warnings;

my $input_file    = "INPUT.txt";

open ( OUTPUT, ">OUTPUT.txt" );

file_in_directory();

close OUTPUT;


sub file_in_directory {

   my $path       = "experiment/";

   my @unsort_output;
   my @not_included;
   open ( INFILE, "<", $input_file);
   while (<INFILE>){
      if ( $_ =~ /NOT_INCLUDED/){
          my @file = $_;
          foreach my $file (@file) {
              $file =~ s/NOT_INCLUDED=//;
              push @not_included, $file;
          }
      }
   }
   close INFILE;

   opendir ( DIR, $path ) || die "Error in opening dir $path\n";
   while ( my $filelist = readdir (DIR) ) {
      chomp $filelist;
      next if ( $filelist =~ m/\.list$/ );
      next if ( $filelist =~ m/\.swp$/ );
      next if ( $filelist =~ s/\.//g);
      foreach $_ (@not_included){
         chomp $_;
         my $not_included = "$_";
         if ( $filelist eq $not_included ){
            next;
         }

      push @unsort_output, $filelist;         
    }

   closedir(DIR);

   my @output = sort @unsort_output;
   print OUTPUT @output;   
}

Я хочу вывести список всех файлов в этом каталогекроме списка файлов в файле input.txt «NOT_INCLUDED».

Output1.sv
Output2.sv
Folder1
Folder2

Но вывод, который я получаю, по-прежнему включал этот нежелательный файл.

Ответы [ 2 ]

2 голосов
/ 24 июня 2019

Эта часть кода не имеет смысла:

   while ( my $filelist = readdir (DIR) ) {
      ...
      foreach $_ (@not_included){
         chomp $_;
         my $not_included = "$_";
         if ( $filelist eq $not_included ){
            next;
         }  # (1)

      push @unsort_output, $filelist;  # (2)
    }

Этот код содержит три открывающие скобки ({), но только две закрывающие скобки (}). Если вы попытаетесь запустить свой код как есть, произойдет сбой с синтаксической ошибкой.

Линия push (отмечена (2)) является частью цикла foreach, но с отступом, как если бы она находилась снаружи. Либо следует добавить отступ больше (для выравнивания с (1)), либо вам нужно добавить } перед ним. Ни одна из альтернатив не имеет большого смысла:

  • Если push находится вне цикла foreach, то оператор next (и весь цикл foreach) не действует. Это может быть просто удалено.
  • Если push находится внутри цикла foreach, то каждая запись в каталоге ($filelist) будет нажиматься несколько раз, по одному для каждой строки в @not_included (за исключением имен, перечисленных где-то в @not_included; те будут толкаться в один раз меньше).

Есть несколько других проблем. Например:

  • $filelist =~ s/\.//g удаляет все точки из имени файла, преобразуя, например, file_c.sv в file_csv. Это означает, что он никогда не будет совпадать с NOT_INCLUDED=file_c.sv во входном файле.
  • Хуже того, часть next if s/// означает, что цикл пропускает все файлы, имена которых содержат точки, такие как Output1.sv или Output2.sv.
  • Результаты печатаются без разделителей, поэтому вы получите что-то вроде Folder1Folder1Folder1Folder2Folder2Folder2file_afile_afile_bfile_b в OUTPUT.txt.
  • Глобальные переменные используются без причины, например INFILE и DIR.

Вот как я бы структурировал код:

#!/usr/intel/perl
use strict;
use warnings;

my $input_file = 'INPUT.txt';

my %is_blacklisted;
{
    open my $fh, '<', $input_file or die "$0: $input_file: $!\n";
    while (my $line = readline $fh) {
        chomp $line;
        if ($line =~ s!\ANOT_INCLUDED=!!) {
            $is_blacklisted{$line} = 1;
        }
    }
}

my $path = 'experiment';

my @results;
{
    opendir my $dh, $path or die "$0: $path: $!\n";
    while (my $entry = readdir $dh) {
        next
            if $entry eq '.' || $entry eq '..'
            || $entry =~ /\.list\z/
            || $entry =~ /\.swp\z/
            || $is_blacklisted{$entry};

        push @results, $entry;
    }
}

@results = sort @results;

my $output_file = 'OUTPUT.txt';
{
    open my $fh, '>', $output_file or die "$0: $output_file: $!\n";
    for my $result (@results) {
        print $fh "$result\n";
    }
}

Содержимое INPUT.txt (точнее, части после NOT_INCLUDED=) считывается в хеш (%is_blacklisted). Это позволяет легко искать записи.

Затем мы обрабатываем записи каталога. Мы пропускаем . и .. (я полагаю, они вам не нужны), а также все файлы, заканчивающиеся *.list или *.swp (что было в вашем исходном коде). Мы также пропускаем любой файл, который находится в черном списке, т. Е. Был указан как исключенный в INPUT.txt. Остальные записи собраны в @results.

Мы сортируем наши результаты и записываем их в OUTPUT.txt, по одной записи в строке.

1 голос
/ 24 июня 2019

Не слишком сильно отклоняясь от вашего кода, вот решение.Пожалуйста, найдите комментарии:

#!/usr/intel/perl
use strict;
use warnings;
my $input_file    = "INPUT.txt";
open ( OUTPUT, ">OUTPUT.txt" );
file_in_directory();
close OUTPUT;

sub file_in_directory {
    my $path       = "experiment/";
    my @unsort_output;
    my %not_included; # creating hash map insted of array for cleaner and faster implementaion.
    open ( INFILE, "<", $input_file);
    while (my $file = <INFILE>) {
        if ($file =~ /NOT_INCLUDED/) {
            $file =~ s/NOT_INCLUDED=//;
            $not_included{$file}++; # create a quick hash map of (filename => 1, filename2 => 1)
        }
    }
    close INFILE;
    opendir ( DIR, $path ) || die "Error in opening dir $path\n";
    while ( my $filelist = readdir (DIR) ) {
        next if $filelist =~ /^\.\.?$/xms; # discard . and .. files
        chomp $filelist;
        next if ( $filelist =~ m/\.list$/ );
        next if ( $filelist =~ m/\.swp$/ );
        next if ( $filelist =~ s/\.//g);
        if (defined $not_included{$filelist}) {
            next;
        }
        else {
            push @unsort_output, $filelist;
        }
    }
    closedir(DIR);  # earlier the closedir was inside of while loop. Which is wrong.
    my @output = sort @unsort_output;
    print OUTPUT join "\n", @output;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...