解决Perl错误:"使用未初始化的值"

时间:2017-08-07 12:29:59

标签: regex perl

为了澄清以下帖子,我们有自动要求将运送信息发送到在线平台,以便用户可以跟踪他们的订单。我们通过电子邮件收到每日.csv文件,我们必须从字段中提取唯一的Shopify订单参考(字段的最后10位数字),保存修改后的.csv文件并上传到FTP站点,以便跟踪引用可以匹配到具体的顺序。

前一位同事在Perl中编写了一个处理此问题的应用程序,但它没有用,我根本没有使用Perl的经验!

该程序由一名观察员调用"监视文件,代码如下:

use strict;
use warnings;

use Datatools::Watcher;

my $hotfolder = '\\gen-svr-01\users\DATA\MW\DMO_Report_IO\INPUT';
my $process   = '"C:\Workspace\bin\WS_DMO_Report_Manipulation_v1.0.pl"';
my @backup    = ('\\gen-svr-01\users\DATA\MW\DMO_Report_IO\ARCHIVE');

watcher($hotfolder,$process,\@backup);

主要代码(PERL PROGRAM)是:

use strict;
use warnings;
use File::Copy;
use Datatools::Watcher;


my $output = '\\gen-svr-01\users\DATA\MW\DMO_Report_IO\OUTPUT';
my $desthotfolder = '\\gen-svr-01\users\DATA\MW\Data_TO_MWS_FTP_TEST';


my $shopifyPos    = 0;            
my $shopifyNew    = "";
my $header        = 1;                  


my $inputfile = $ARGV[0];    
my ($path,$file,$extention) = $inputfile =~ m/ \A (.+\/) (.+\d\d\d\d) .+ ([.]\w{3}) \z/ixms;

my $outputfilename = $file . "_FORMATTED" . $extention;
$outputfilename =~ s/.~#~//;
my $outputfile = "$output\\$outputfilename";


open (INPUT, $inputfile) or die "Could not open input file: $inputfile\n";
open (OUTPUT, ">$outputfile") or die "Could not open output file: $outputfile\n";

while (my $record = <INPUT>){
chomp $record;
my @field = parse_csv($record);
  if ($header == 1){
            print OUTPUT $record . "\n";
            $header = 0;
            next;
        } else {
            $shopifyNew = substr $field[$shopifyPos], -10;
            splice (@field, 0, 1, $shopifyNew);
            print OUTPUT join(',',@field) . "\n";
            next;
            }
    }

close INPUT;
close OUTPUT;


my $destfile = "$desthotfolder\\$outputfilename";

move $outputfile, $destfile or die "Could not move output file: $outputfile\nto: $destfile\n";

print "\nProcessing complete\n";


sub parse_csv {
my ($shift) = @_;
my $text = $shift;      # record containing comma-separated values
my @new  = ();

push(@new, $+) while $text =~ m{
    # the first part groups the phrase inside the quotes.
    # see explanation of this pattern in MRE
    "([^\"\\]*(?:\\.[^\"\\]*)*)",?
       |  ([^,]+),?
       | ,
   }gx;
   push(@new, undef) if substr($text, -1,1) eq ',';
   return @new;      # list of values that were comma-separated
}

当程序运行时,&#34; Watcher&#34;详细说明如下:

  

文件所见,处理文件\\ gen-svr-01 \ users \ DATA \ MW \ DMO_Report_IO \ INPUT / OrderTracking.csv使用连接中未初始化的值$ file&lt;。&gt;或字符串在C:\ Workspace \ bin \ WS_DMO_Report_Manipulation_v1.0.pl第47行。   在连接中使用未初始化的值$ extention&lt;。&gt;或C:\ Workspace \ bin \ WS_DMO_Report_Manipulation_v1.0.pl第47行的字符串。

     

处理完成

第47行引用以下代码:

my $outputfilename = $file . "_FORMATTED" . $extention;

在输出文件夹中,有一个名为&#34; _FORMATTED&#34;的文件。 (没有文件扩展名)

我找到了一个解决方案,从我有限的理解中我不会想到变量:文件和扩展名正在定义,但我不知道如何纠正!

1 个答案:

答案 0 :(得分:3)

了解此代码中第47行是有帮助的。我认为这就是这条线:

my $outputfilename = $file . "_FORMATTED" . $extention;

因此,此时$file$extention都未初始化。它们都应该在前一行中初始化:

my ($path,$file,$extention) =
  $inputfile =~ m/ \A (.+\/) (.+\d\d\d\d) .+ ([.]\w{3}) \z/ixms;

因此,您的$inputfile似乎与正则表达式不匹配。这给我们留下了两个选择:

  1. $inputfile根本没有设置(这意味着它没有被传递给程序)。
  2. $inputfile格式不正确以匹配正则表达式。
  3. 要弄清楚我们在这里遇到哪些问题,请在尝试设置$file$extention的行之前添加以下验证行:

     die "No input file given\n" unless $inputfile;
     die "Input file name ($inputfile) is the wrong format\n"
       unless $inputfile =~ / \A (.+\/) (.+\d\d\d\d) .+ ([.]\w{3}) \z/ixms;
    

    更新:根据您对问题的最新更新,我可以看到您正在运行该程序并将其传递给文件名\\gen-svr-01\users\DATA\MW\DMO_Report_IO\INPUT/OrderTracking.csv

    让我们仔细看看你的正则表达式。

    m/ \A (.+\/) (.+\d\d\d\d) .+ ([.]\w{3}) \z/ixms
    

    最后的/x选项意味着正则表达式编译器会忽略字符串中的任何文字空格。所以我们也可以这样做。让我们分解各个部分试图匹配的内容:

    • \A:匹配字符串的开头
    • (.*\/):匹配字符串中最后一个/的所有内容。它将匹配的子字符串捕获到$1。这是代码中$path中存储的内容。它是您的文件所在的目录。
    • (.+\d\d\d\d):匹配任意字符后跟四位数字中的一个或多个。它存储在$2中,在您的代码中,它以`$ file``结尾。它是文件名的主要部分。
    • .+:匹配一个或多个字符。任何人物。你的代码对这些字符没有任何作用。
    • ([.]\w{3}):匹配一个点后跟三个“单词”字符(基本上是字母数字)。这会被捕获到$3中,最终会出现在$extention变量中。
    • \z:匹配字符串的结尾。

    将所有这些放在一起,你有一个正则表达式,它寻找文件名并将它们分成三个部分 - 路径,名称和扩展名。唯一的复杂因素是文件名部分需要包含四个连续的数字。你的文件名是OrderTracking - 它不包含那些必需的数字。所以正则表达式不匹配,你的变量也没有设置。

    编写此程序时,假定文件名包含四位数字。您尝试处理的文件不包含数字,因此程序失败。

    我们无法建议你如何解决这个问题。您需要与提供输入文件的人员交谈,并找出他们为什么开始向您发送具有不同名称格式的文件。一旦你知道了,就可以决定解决问题的最佳方法。