为了澄清以下帖子,我们有自动要求将运送信息发送到在线平台,以便用户可以跟踪他们的订单。我们通过电子邮件收到每日.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;的文件。 (没有文件扩展名)
我找到了一个解决方案,从我有限的理解中我不会想到变量:文件和扩展名正在定义,但我不知道如何纠正!
答案 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
似乎与正则表达式不匹配。这给我们留下了两个选择:
$inputfile
根本没有设置(这意味着它没有被传递给程序)。$inputfile
格式不正确以匹配正则表达式。要弄清楚我们在这里遇到哪些问题,请在尝试设置$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
- 它不包含那些必需的数字。所以正则表达式不匹配,你的变量也没有设置。
编写此程序时,假定文件名包含四位数字。您尝试处理的文件不包含数字,因此程序失败。
我们无法建议你如何解决这个问题。您需要与提供输入文件的人员交谈,并找出他们为什么开始向您发送具有不同名称格式的文件。一旦你知道了,就可以决定解决问题的最佳方法。