如何格式化我的 Perl 代码,以便我可以从命令窗口更改我的调用并测试或不测试它?

Posted

技术标签:

【中文标题】如何格式化我的 Perl 代码,以便我可以从命令窗口更改我的调用并测试或不测试它?【英文标题】:How to format my Perl code such that I can alter my calling from the command window and either test or not test it? 【发布时间】:2014-07-02 21:11:33 【问题描述】:

我所拥有的:详细地说,我目前有一个指定源目录和目标存档目录的 main 函数。每个月底,必须将上个月的数据移到归档目录中。我已经把这一切都弄清楚了。子例程是使用 localtime 函数选择本地时间,然后在我测试一些条件后,它返回上个月和上一年作为存档目录中新文件夹的名称。

我需要什么:我在子例程中有一个测试设置,当 $test = 1 时,测试运行并指定我可以输入的唯一年份和月份,而当 test = 0 时,测试没有t 运行,代码正常工作。我希望能够将文件的名称写入代码之外的命令行,并且无论我是否运行测试(比如 perl -e archive.pl 1 运行测试)都有某种启动来触发和 perl -e arhcive.pl 0 正常运行代码)。

我是 Perl 的新手,但这是我的子程序:

sub dateDirectory 
    my $lt = localtime();            # establish a variable lt for the localtime (includes, sec, min, hour, mday, mon, year)
    my $year = $lt->year+1900;       # establish a variable year and add 1900 to it as it prints only 100+ value
    my $mon = $lt->mon+1;            # establish a variable mon for month and add 1 as it is a zero-indexed language

    my $test = 1; # establish the test variable to run a unit test if test = 1 and don't run it if test = 0

    if ($test == 1) 
        $year = 2005;
        $mon = 3;
    

    my $prev_mon = $mon - 1;
    my $prev_year = $year - 1;
    my $prev_yearmonth = "year$prev_mon";

    if ($mon == 1) 
        $prev_mon = 12;
        $year = $prev_year;
        $prev_yearmonth = "$year$prev_mon";
    

    my $prev_monlength = length($prev_mon);

    if ($prev_monlength == 1) 
        $prev_yearmonth = sprintf "%d%02d", $year, $prev_mon;
    

    return ($prev_yearmonth);

【问题讨论】:

【参考方案1】:

使用@ARGV 访问传递给 perl 脚本的参数。

在这种情况下,我建议您使用Getopts::Long 来捕获旨在触发您的特殊处理的参数:

use strict;
use warnings;

use Getopt::Long;

GetOptions(
    'test'   => \my $test,
);

print $test ? "In Testing mode\n" : "Regular mode\n";

然后,当您想处于测试模式时,只需执行如下脚本即可:

perl yourscript.pl --test

【讨论】:

如果我只是通过在命令行中输入 --test 来执行我的测试,我如何访问测试设置的条件? 使用 --test 执行代码是否只是将 test 的值设置为 1?【参考方案2】:

就像 Miller 说的,Getopts::Long 是为您的 perl 程序提供命令行选项的好方法。不过,我想添加一个示例,说明如何使用参数将 $test 设置为 0 或 1。

#!/usr/bin/perl

use strict;
use warnings;

my $test = $ARGV[0];

if ( not defined $test ) 
    die "please supply an argmument";


if ( $test == 1 ) 
    print "test mode\n";
 else 
    print "normal mode\n";

尝试用它调用perl test.pl 0perl test.pl 1

【讨论】:

我看到了 Getopts::Long 的使用,但我认为您的解决方案最适合我的问题。但是,我已经玩了几天了,无法弄清楚如何将输入测试参数合并到主例程中,同时将条件合并到子例程中。我试着把我的 $test = @_;进入子例程以从主函数调用我的输入,但它不起作用。 @_ 是一个数组,您在标量上下文中调用它。尝试my ($test) = @_;,如果这不起作用,您可以发布一些代码并提出另一个问题。 不,那没用。如果我将你的整个代码(减去 use strict 和 use 警告)包含在我的子程序中,我可以让它完美地工作,我有所有其他条件。但是如果我尝试使用 my $test = $ARGV[0];部分进入主程序,它停止工作。这就是为什么我试图将它调用到子程序中。 @user3799015,我必须查看您的代码才能弄清楚。您的脚本顶部确实有use strictuse warnings 吗?他们指出错误。如果你把它们拿出来,错误仍然存​​在,但消息不会显示,它们可能会导致其他问题。 是的,我愿意。代码正常运行我只是不认为它完全按照我想要的方式运行,除非我将整个代码包含在子例程中。我刚刚被告知从子程序进行测试是不好的做法。【参考方案3】:

您可能想考虑学习使用 CPAN,并安装 DateTime 模块。它可以以正确的方式轻松完成各种日期数学运算。

use Carp qw< croak >;
use DateTime;

sub dateDirectory 
    my ($year, $month) = @_;

    # croak throws an exception at the calling function.
    croak "dateDirectory requires both year and month or neither be specified\n"
        if (
            ($year && !$month)
         || (!$year && $month)
        );

    # Get default value of "last month", if not specified.
    if( !$year ) 
        my $date = DateTime->now()->subtract( months => 1 );

        $year = $date->year();
        $month = $date->month();
    

    return "%04d%02d", $year, $month;

您可以编写测试代码,使用您想要的任何年份和月份调用 dateDirectory。

【讨论】:

我一定会安装模块谢谢! :) 确定测试代码会很好。【参考方案4】:

我喜欢 perl,但我使用了带有 cron 的 log rotate 来代替这个基本功能。

http://www.adminschoice.com/crontab-quick-reference/

http://linuxcommand.org/man_pages/logrotate8.html

【讨论】:

欢迎来到 ***!如果您在答案中发布链接中的相关引用,这将很有用,这样用户就不必去搜索它们了。

以上是关于如何格式化我的 Perl 代码,以便我可以从命令窗口更改我的调用并测试或不测试它?的主要内容,如果未能解决你的问题,请参考以下文章

从 Bash 或 Perl 脚本运行 SQL 语句?

perl中的位选择

Perl 的 system() 如何打印它正在运行的命令?

如何以表格格式调用我的输出以便我可以查询它?

如何将 Perl 的 system() 的输出重定向到文件句柄?

如何将变量添加到我的 Perl 单行中?