这些引用的字符串如何被perl .pm文件中的值替换?

时间:2017-03-31 09:17:59

标签: perl

下面是.pm文件中的Perl代码,它应该用一些值替换指定的字符串(在"引号"中)。但它没有发生。谁能解释一下这段代码中发生了什么?

package SomePackage;

require Exporter;

@ISA    = qw(Exporter);
@EXPORT = qw(send_request, create_mmd_and_transfer, update_mmd_file);

sub send_request {
    my ( $service, $action, $torole ) = @_;

    my ( $seller_request_mmd );

    my $replace_contents = ();
    $replace_contents{"REPLACE_Service"}        = $service;
    $replace_contents{"REPLACE_RequestAction"}  = $action;
    $replace_contents{"REPLACE_TradingPartner"} = $torole;
    $replace_contents{"REPLACE_Requestxml"}     = "Request.xml";

    create_mmd_and_transfer( \%replace_contents, $seller_request_mmd, "/MMD.xml" );
}

sub create_mmd_and_transfer {

    my $local_replace_contents = shift;
    my $input_mmd              = shift;
    my $local_output_mmd       = shift;
    my $output_mmd             = shift;

    update_mmd_file( "$input_mmd", "temp_mmd_file.xml", $local_replace_contents );
}

sub update_mmd_file {

    my $input_file  = shift;
    my $output_file = shift;
    my $contents    = shift;

    open( MMD_FILE, "<$input_file" )
            or main::error_exit(" Cannot open MMD file template $input_file \n $input_file not found int the Templates folder \n Please place the same and then run the script ");

    open( TEMP_MMD_FILE, ">$output_file" );

    while ( <MMD_FILE> ) {

        s/^M//g;    # Getrid of the ^Ms

        foreach my $content ( keys( %$contents ) ) {

            my $exact_value = ${%$contents}{$content};

            if ( $main::test_scenario =~ /^Invalid Request Action \a\n\d Service/
                and ( $content =~ /REPLACE_Service|REPLACE_RequestAction/i ) ) {
            }
            else {

                if ( $exact_value ne "" ) {
                    s/$content/$exact_value/g;
                }
            }
        }

        print TEMP_MMD_FILE;
    }

    close MMD_FILE;
    close TEMP_MMD_FILE;
}

2 个答案:

答案 0 :(得分:0)

以下内容不会使您的脚本有效,只需为以后的某些问题创建更好的基础。

在您考虑在此处发布perl问题之前:

1。)添加到脚本的顶部:

use strict;
use warnings;

在没有这两行的情况下在这里发布代码,没有人会打扰甚至尝试阅读代码。

2.)使用perl -c SomePackage.pm进行检查。如果它会告诉您:SomePackage.pm syntax OK - 您可以开始考虑在此处发布问题。 ;)

脚本的一些基本问题:

package SomePackage;
use strict;   # see the above
use warnings;

require Exporter;

# these variables are defined outside of this package, so, tell perl this fact. use the `our`
our @ISA    = qw(Exporter);
#the use warnings will warn you about the following line
# @EXPORT = qw(send_request, create_mmd_and_transfer, update_mmd_file);
#the correct one is without commas
our @EXPORT = qw(send_request create_mmd_and_transfer update_mmd_file); #not saying anything about the @EXPORT rudeness. :)

#my $replace_contents = ();
#the $replace_contents is a scalar. Bellow you using a hash. So,
my %replace_contents;
#or use the scalar but the lines bellow should use the hashref notation, e.g.
# $replace_contents->{"REPLACE_Service"} = $service;
# you decide. :)

# the seller_request_mmd contains undef here.
create_mmd_and_transfer( \%replace_contents, $seller_request_mmd, "/MMD.xml");
# also bellow, in the subroutine definition it wants 4 arguments.
# indicates a problem...

# using 2-arg open is not the best practice.
# Also, you should to use lexical filehandles
# open (MMD_FILE, "<$input_file") 
# better
open (my $mmd_file, '<', $input_file)
# of course, you need change every MMD_FILE to $mmd_file
# check the result of the open and die if not successful
# or you can use the 
use autodie;

# instead of $exact_value = ${%$contents}{$content};
# you probably want
my $exact_value = $contents->{$content};

缩进你的代码!

以上所有内容都是关于语法问题而不解决有关代码“逻辑”的任何问题。

Ps:我还是初学者,所以,其他人肯定会发现上述代码存在更多问题。

答案 1 :(得分:0)

确定。以下是我为测试这一点所做的工作。

首先,您没有提供输入文件或用于调用模块的代码。所以我发明了它们。我做了最简单的输入文件:

REPLACE_Service
REPLACE_RequestAction
REPLACE_TradingPartner
REPLACE_Requestxml

这个驱动程序:

#!/usr/bin/perl

use strict;
use warnings;

use SomePackage;

send_request('foo', 'bar', 'baz');

sub error_exit {
  die @_;
}

第一次,我跑了,我收到了这个错误:

  

在测试线8处调用未定义的子程序&amp; main :: send_request。

那是因为你的@EXPORT行错了。你有:

@EXPORT = qw(send_request, create_mmd_and_transfer, update_mmd_file);

qw(...)的要点是你不需要逗号。所以我纠正了:

@EXPORT = qw(send_request create_mmd_and_transfer update_mmd_file);

然后我重新运行程序并得到了这个错误:

  

无法打开MMD文件模板
   找不到Templates文件夹   请放置相同的内容,然后在测试第11行运行脚本。

看起来有些东西不见了。我更改了错误消息,添加了变量插值应该发生的位置的指示符:

open( MMD_FILE, "<$input_file" )
        or main::error_exit(" Cannot open MMD file template <$input_file> \n <$input_file> not found int the Templates folder \n Please place the same and then run the script ");

然后错误消息如下所示:

  

无法打开MMD文件模板&lt;&gt;    &LT;&GT;找不到Templates文件夹   请放置相同的内容,然后在测试第11行运行脚本。

所以很明显$input_file子程序中没有设置update_mmd_file()变量。追溯该变量后,我们发现此值最初是$seller_request_mmd中的send_request()变量。但是在send_request()中,您声明$seller_request_mmd,但您从未给它赋值。让我们这样做:

my ( $seller_request_mmd ) = 'test_input.txt';

现在,当我运行你的程序时,它运行完成没有任何错误。我发现生成了一个新的temp_mmd_file.xml。但它与输入文件完全相同。因此需要进行更多调查。

深入研究update_mmd_file()子程序,我们发现了这条有趣的路线:

my $exact_value = ${%$contents}{$content};

我认为您正在尝试从$contents中提取值,这是一个哈希引用。但是你的语法错了。你可能的目标是:

my $exact_value = ${$contents}{$content};

但大多数Perl程序员更喜欢使用箭头符号来处理参考查找。

my $exact_value = $contents->{$content};

进行更改并重新运行程序,我得到一个包含以下内容的输出文件:

foo
bar
baz
Request.xml

这正是我的预期。所以该计划现在有效。

但仍有许多工作要做。正如你多次被告知的那样,你应该总是添加:

use strict;
use warnings;

代码。这会在您的代码中发现许多潜在的问题 - 您应该修复它们。

说实话,这对我来说就像你在行走前试图跑步一样。我建议花一些时间在a good Perl introductory book之前完成我的更多Perl工作。

您的问题中缺少许多有用的信息。如果您向我们展示了您的驱动程序和输入数据,那么找到解决方案的时间不会太长。