【问题标题】:Perl script running itself with new parameters使用新参数运行自身的 Perl 脚本
【发布时间】:2017-03-07 20:57:02
【问题描述】:

我正在比较几个列表以找出不匹配的地方,并认为这是一个很好的机会,可以利用我过去的一点 Perl 经验。

我的代码将数据从两个文件中拆分出来,让我可以轻松访问所需的数据(主要是文章编号和数量)。 然后,它将一个文件(替换部件)与另一个文件(部件列表)进行比较。 但是,如果在替换零件列表中找到一个套件(文章编号以 K 开头),它将再次调用相同的 Perl 脚本,但使用套件中的零件列表而不是替换零件列表。 在运行了 Kit 的脚本后,我希望它能够继续从它调用自身的位置运行原始脚本。

问题是它会首先完全运行脚本(从我的输出中可以看出),然后再开始运行 Kit 的脚本。 此外,脚本的第二次运行(用于套件)在中途开始!跳过创建标头和我的大部分数据文件。

脚本接受参数:partslist.txt replacementparts.txt(或 Kitparts)和一个可选的 K 作为第三个参数(如果它是 Kit)。 如果脚本看起来很乱,请原谅,我对此很陌生:

#!/usr/bin/perl

use strict;
use warnings;

# quit unless we have the correct number of command-line args
my $num_args = $#ARGV + 1;

if ( $num_args != 2 && $num_args != 3 ) {
    print "$num_args\nUsage: perl perl.pl parts_file.txt replacements_file.txt \(optionally add \"k\" as a third parameter if a Kit\)\n";
    exit;
}

# initialise files
my $file1 = $ARGV[0];
my $file2 = $ARGV[1];

open( my $fh_replacements, "<", $file2 )
        or die "Could not open file '$file2' $!";

open( my $writefile_fh, ">", $writefile )
        or die "Could not open file '$writefile' $!";

# initialise global variables
my $count = 1;
my @splitter;
my @splitter2;

# decide header based on whether we are dealing with a Kit
if ( lc $ARGV[2] ne "k" ) {
    print {$writefile_fh} "File $file2 results:\n\n";
}
else {
    print {$writefile_fh} "\tMontagekit $ARGV[1]:\n";
}

# check the data
while ( my $row = <$fh_replacements> ) {

    if ( $count >= 10 && $row ne "" && $row ne "\n" )
    {    #start at row 10, don't use NULL or newline rows

        my $hits = 0;

        open( my $fh_parts, "<", $file1 ) or die "Couldn't reopen '$file1' $!";

        @splitter = split( '\s*\|\s*', $row );    #split by | with any number of spaces around it

        if ( substr( $splitter[1], 0, 1 ) ne "K" ) {    #check for montageKit

            foreach ( @splitter ) {

                my @line = <$fh_parts>;

                for ( @line ) {

                    $_ =~ s/\x0//g;                     #weird windows64bit related spaces fix

                    if ( $_ =~ /$splitter[1]/ ) {
                        $hits++;
                        $splitter[6] =~ s/\,/\./;
                        @splitter2 = split( /(?<!,)\t/, $_ );    #split by tabs
                    }
                }
            }

            close $fh_parts;

            if ( $hits == 0 ) {
                print {$writefile_fh} "$splitter[1] not matched!\n";
            }    #not found
            elsif ( $hits == 1 ) {    #found

                if ( $splitter[6] == $splitter2[1] ) {
                    print {$writefile_fh} "$splitter[1] matched!\tQuantity match!\n";
                }
                else {
                    print {$writefile_fh} "$splitter[1] matched!\tQuantity mismatch: $splitter[6] - $splitter2[1] \(replacements - parts\)\n";
                }
            }
            else {
                print {$writefile_fh} "$splitter[1] matched $hits times!\n";
            }    #found multiple instances
        }
        else {    #If kit is found, send back to separate instance of program to run for the Kit
            local @ARGV = ( $ARGV[0], $splitter[1] . "\.txt", "k" );
            do 'perl.pl';
        }
    }

    $count++;
}

if ( lc $ARGV[2] ne "k" ) {
    print {$writefile_fh} "\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n";
}

输出:

File 2716576.txt results:

testarticle not matched!
00000126 matched!   Quantity mismatch: 1.0000 - 5 (replacements - parts)
00750020 matched!   Quantity match!
testarticle not matched!
testarticle not matched!
testarticle not matched!
00170018 matched 3 times!
testarticle not matched!
testarticle not matched!
testarticle not matched!
///////////////////
000222 matched! Quantity match!
00050496 matched!   Quantity match!

输出中只有最后两行来自 Kit 文件。

我想这会比复制粘贴相同的代码为 Kit 再次运行要好。如果我不能让它工作,那仍然是最后的选择。

谁能告诉我哪里出错了?我觉得有些变量正在延续,和/或脚本的第二次运行没有从我想要的地方开始。不过,我不确定如何解决这个问题,我已经尝试了所有可以进行的故障排除,因此我们将不胜感激。

【问题讨论】:

  • 这将受益于我认为的一些示例数据。
  • 哦。确实使用 sub 代替! /// 请提供说明问题的数据,以及您期望的输出

标签: perl


【解决方案1】:

我想你只需要声明一个可以递归调用的子程序。

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

# quit unless we have the correct number of command-line args
my $num_args = $#ARGV + 1;
if ($num_args != 2 && $num_args != 3) {
    print "$num_args\nUsage: perl perl.pl parts_file.txt replacements_file.txt \(optionally add \"k\" as a third parameter if a Kit\)\n";
    exit;
}

process_kit (@ARGV);

sub process_kit {
    my ($file1, $file2, $argv2) = @_;

    open( my $fh_replacements, "<", $file2 )    
        or die "Could not open file '$file2' $!"; 
    open( my $writefile_fh, ">", $writefile )
        or die "Could not open file '$writefile' $!";

# initialise local variables
    my $count = 1;
    my @splitter;
    my @splitter2;

# decide header based on whether we are dealing with a Kit
    if (lc $argv2 ne "k") { 
        print {$writefile_fh} "File $file2 results:\n\n";} 
    else { 
        print {$writefile_fh} "\tMontagekit $ARGV[1]:\n";}
# check the data
    while ( my $row = <$fh_replacements> ) {
        if ( $count >= 10 && $row ne "" && $row ne "\n" ) {  #start at row 10, don't use NULL or newline rows
            my $hits = 0;
            open( my $fh_parts, "<", $file1 ) or die "Couldn't reopen '$file1' $!";
            @splitter = split( '\s*\|\s*', $row );    #split by | with any number of spaces around it
            if (substr($splitter[1],0,1) ne "K") {    #check for montageKit
                foreach (@splitter) {
                    my @line = <$fh_parts>;
                    for (@line) {
                        $_ =~ s/\x0//g;    #weird windows64bit related spaces fix
                        if ( $_ =~ /$splitter[1]/ ) {
                            $hits++;
                            $splitter[6] =~ s/\,/\./;
                            @splitter2 = split( /(?<!,)\t/, $_ );    #split by tabs
                        }
                    }
                }
                close $fh_parts;
                if ( $hits == 0 ) { print {$writefile_fh} "$splitter[1] not matched!\n"; }  #not found
                elsif ( $hits == 1 ) {                                                      #found  
                    if ( $splitter[6] == $splitter2[1] ) {
                        print {$writefile_fh} "$splitter[1] matched!\tQuantity match!\n";
                    }
                    else {
                        print {$writefile_fh} 
                        "$splitter[1] matched!\tQuantity mismatch: $splitter[6] - $splitter2[1] \(replacements - parts\)\n";
                    }
                }
                else { print {$writefile_fh} "$splitter[1] matched $hits times!\n"; }           #found multiple instances
            }
            else {   #If kit is found,run again the program for the Kit
                process_kit($file1, $splitter[1]."\.txt", "k");
            }
        }

        $count++;
    }
    if (lc $argv ne "k") { print {$writefile_fh} "\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n";}
}

【讨论】:

  • 感谢您的建议!似乎子程序是个好主意。但是,我遇到了与使用此代码之前相同的问题:仅写入了套件输出的一部分,并且写入不正确(在输出的其余部分之后,而不是在调用它的中间)。
猜你喜欢
  • 1970-01-01
  • 2018-09-18
  • 2011-02-23
  • 1970-01-01
  • 2012-08-29
  • 2015-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多