Сохранить все данные в массиве, отфильтровать дублированные данные, сравнить данные между массивами и удалить соответствующие данные - PullRequest
0 голосов
/ 06 сентября 2018

У меня есть некоторые проблемы с моим скриптом. Проблемы:

  1. Значение $ str или @matchedPath иногда пустое, когда я печатаю. Это не случайно, это происходит только с определенным путем в файле table.txt, который я не могу понять, почему?
  2. Как печатать как результат, потому что я не могу найти правильное местоположение файла или каталог файла table.txt, потому что я поместил все пути в массив, отфильтровал его и сравнил с соответствующим правильным расположением файла table.txt, из-за этого при распечатке отсутствует какое-либо местоположение.

Пример пути, который содержат файлы /home/is/latest/table.txt, текст, выделенный жирным шрифтом, - это требуемый путь в table.txt,

##WHAT PATH IS_THAT,Backup
a   b/c/d   B
a   b/c/d/e  B
a   b/c/d/e/f  B
a   b/c/d/g  B

Пример пути, который содержат файлы /home/are/latest/table.txt, средние тексты - это требуемый путь в table.txt,

##WHAT PATH IS_THAT,Backup
a   b/c/d/j B

например. файл list.txt содержит,

rty/b
uio/b/c
qwe/b/c/d
asd/b/c/d/e
zxc/b/c/d/e/f
vbn/c/d/e
fgh/j/k/l

Ожидаемый результат:

Unmatched Path         : b/c/d/g
table.txt file location: /home/is/latest/table.txt

Unmatched Path         : b/c/d/j
table.txt file location: /home/are/latest/table.txt

Ниже мой подробный сценарий,

#!/usr/perl/5.14.1/bin/perl 

# I want to make a script that automatically compare the path in table.txt with list.txt
#table.txt files is located under a parent directory and it differs in the subdirectory.
#There is about 10 table.txt files and each one of it need to compare with list.txt
#The objective is to print out the path that are not in the list.txt

use strict;
use warnings;
use Switch;
use Getopt::Std;
use Getopt::Long;
use Term::ANSIColor qw(:constants);
use File::Find::Rule;
use File::Find;
use File::Copy;
use Cwd;
use Term::ANSIColor;

my $path1='/home';                                                      #Automatically search all table.txt file in this directory even in subdirectory
my $version='latest';                                                   #search the file specified subdirectory e.g. /home/is/latest/table.txt and /home/are/latest/table.txt
my $path2='/list.text';                                                 #there is about 10 table.txt files which contain specified paths in it.

$path1 =~ s/^\s+|\s+$//g;
$version =~ s/^\s+|\s+$//g;
$path2 =~ s/^\s+|\s+$//g;

my @files = File::Find::Rule->file()
                            ->name( 'table.txt' )
                            ->in( "$path1" );

my @symlink_dirs = File::Find::Rule->directory->symlink->in($path1);      #If the directory is a symlink, in my case 'latest' is a symlink directory
print colored (sprintf ("\n\n\tSUMMARY REPORT"),'bold','magenta');
print  "\n\n_______________________________________________________________________________________________________________________________________________________\n\n";

if ($version eq "latest")
{
    foreach my $dir (@symlink_dirs) 
    {
        my @filess = File::Find::Rule->file()
                                     ->name( 'table.txt' )
                                     ->in( "$path1" );
        my $symDir=($dir."/"."table.txt");
        $symDir =~ s/^\s+|\s+$//g;
        my $wantedPath=$symDir;
        my $path_1 = $wantedPath;
        function($path_1);      

    }
}

else 
{

    for my $file (@files)   
    {

        if ($file =~ m/.*$version.*/)
        {
        my $wantedPath=$file;
            my $path_1 = $wantedPath;
            function($path_1);  
        }
    }
}

sub function
    {

    my $path_1 = $_[0];
    open DATA, '<', $path_1 or die "Could not open $path_1: $!";

    my $path_2 = "$path2";
    open DATA1, '<', $path_2 or die "Could not open $path_2: $!";

################# FOCUSED PROBLEM AREA ##############################       
    my @matchedPath;
    my @matched_File_Path;
    my @unmatchedPath;
    my @unmatched_File_Path;
    my @s2 = <DATA1>;

        while(<DATA>)
        {

        my $s1 = $_;

            if ($s1 =~ /^#.*/) 
            {
            next;
            }

            if ($s1 =~ /(.*)\s+(.*)\s+(.*)\s+/) 
            {
            my $str=($2);
            $str =~ s/\s+//g;

                for my $s2 (@s2)
                {

                    if ($s2 =~ /.*$str/)
                    {
                    push @matchedPath,$str;                                      
                    push @matched_File_Path,$path_1;                                
                    print "matched Path: $str\n\t$path_1\n"; #I don't understand, sometimes I get empty $str value in this. Can anyone help me?
                    last;
                    }
                    else
                    {
                    #print "unmatch:$str\n\t$path_1\n";                     
                    push @unmatchedPath,$str;                                   
                    @unmatched_File_Path,$path_1;
                                        }
                }
            }
        }
        foreach (@unmatchedPath)
        {print "unmatch path: $_\n";}        
        foreach (@matchedPath)
        {print "\nmatch path: $_\n\n";}     

        foreach (@unmatched_File_Path)       
        {print "unmatch File Path: $_\n";}
        foreach (@matched_File_Path)         
        {print "match File Path: $_\n";}

        my @filteredUnmatchedPath = uniq(@unmatchedPath);                   
        my @filteredUnmatched_IP_File_Path =uniq(@unmatched_IP_File_Path); 
         @filteredUnmatchedPath = grep {my $filteredPath = $_; not grep $_ eq $filteredPath, @matchedPath} @filteredUnmatchedPath;
}
        print "@filteredUnmatchedPath\n";   
        print "@filteredUnmatched_IP_File_Path\n";

sub uniq 
{
    my %seen;
    grep !$seen{$_}++, @_;
}



close(DATA);
close(DATA1);

print  "_________________________________________________________________________________________________________________________________________________________\n\n";

1 Ответ

0 голосов
/ 06 сентября 2018

Я думаю, что использовать хеши здесь намного проще
вот что я попробовал: вам придется заменить @all_path вашим массивом, содержащим все пути, где присутствует таблица

use strict;
use warnings;

my @all_path =("some/location/table.txt","some/location_2/table.txt");
my %table_paths;
my %list_paths;

foreach my $path (@all_path)
{
    open (my $table, "<", $path) or die ("error opening file");
    #we create hash, each key is a path
    while (<$table>)
    {
        chomp;
        #only process lines starting with "a" as it seems to be the format of this file
        $table_paths{(split)[1]}=$path if (/^a/); #taking the 2nd element in each line
    }

    close $table;
}

open (my $list, "<", "list.txt") or die ("error opening file");

#we create hash, each key is a path
while (<$list>)
{
    chomp;
    $list_paths{$_}=1;
}

close $list;

#now we delete from table_paths common keys with list, that lefts unmathed
foreach my $key (keys %table_paths)
{
    delete $table_paths{$key} if (grep {$_ =~ /$key$/} (keys %list_paths));
}

#printing unmatched keys
print "unmatched :$_\nlocation: $table_paths{$_}\n\n" foreach keys %table_paths;

Входы

в некоторых / location / table.txt

##WHAT PATH IS_THAT,Backup
a   b/c/d   B
a   b/c/d/e  B
a   b/c/d/e/f  B
a   b/c/d/g  B

в некоторых / location_2 / table.txt

##WHAT PATH IS_THAT,Backup
a   b/c/d/j B

в list.txt

rty/b
uio/b/c
qwe/dummyName/b/c/d
asd/b/c/d/e
zxc/b/c/d/e/f
vbn/c/d/e
fgh/j/k/l

выход:

unmatched: b/c/d/g
location: some/location/table.txt

unmatched: b/c/d/j
location: some/location_2/table.txt
...