Как отформатировать мой код Perl так, чтобы я мог изменить свой вызов из командного окна и либо тестировать, либо не тестировать его?

Что у меня есть: Чтобы уточнить, у меня в настоящее время есть основная функция, которая указывает исходный каталог и целевой каталог архива. В конце каждого месяца данные за последний месяц должны быть перемещены в каталог архива. Я все понял, и хорошо, и вниз. Подпрограмма — это то, что выбирает местное время с помощью функции localtime, а затем, после проверки нескольких условий, она возвращает предыдущий месяц и год в качестве имени новой папки в каталоге архива.

Что мне нужно: у меня есть тестовая настройка в подпрограмме, так что когда $test = 1, тест запускается и указывает уникальный год и месяц, которые я могу ввести, тогда как когда test = 0, тест не запускается и код работает нормально. Я хочу иметь возможность писать имя файла в командной строке вне кода и иметь какую-то инициацию, чтобы запустить тест или нет (например, 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);
}

person John    schedule 02.07.2014    source источник


Ответы (4)


Как сказал Миллер, 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 0 и perl test.pl 1.

person hmatt1    schedule 02.07.2014
comment
Я вижу использование Getopts::Long, но я думаю, что ваше решение лучше всего подходит для моей проблемы. Однако я играл с этим несколько дней и не могу понять, как включить аргумент входного теста в основную процедуру, включив условия в подпрограмму. Я попытался поставить свой $test = @_; в подпрограмму, чтобы вызвать мой ввод из основной функции, но это не сработало. - person John; 07.07.2014
comment
@_ - это массив, и вы вызываете его в скалярном контексте. Попробуйте my ($test) = @_;, и если это не сработает, вы можете опубликовать код и задать другой вопрос. - person hmatt1; 07.07.2014
comment
Нет, это не сработало. Я могу заставить его работать идеально, если включу весь ваш код (за исключением строгого использования и предупреждений об использовании) в свою подпрограмму, где у меня есть все остальные условия. Но если я попытаюсь использовать my $test = $ARGV[0]; частью основной процедуры, она перестает работать. Вот почему я пытался вызвать это в подпрограмме. - person John; 07.07.2014
comment
@ user3799015, мне нужно увидеть ваш код, чтобы понять это. У вас ведь есть use strict и use warnings вверху вашего скрипта, верно? Они указывают на ошибки. Если вы удалите их, ошибки останутся, но сообщения не будут отображаться, и они могут вызвать другие проблемы. - person hmatt1; 08.07.2014
comment
Да. Код работает правильно, я просто не думаю, что он работает так, как я намереваюсь, если я не включу весь код в подпрограмму. Мне только что сказали, что тестирование из подпрограммы - плохая практика. - person John; 08.07.2014

Используйте @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
person Miller    schedule 02.07.2014
comment
Если я просто выполняю свой тест, введя --test в командную строку, как я получу доступ к условиям, установленным тестом? - person John; 07.07.2014
comment
Выполнение вашего кода с --test просто устанавливает значение test равным 1? - person John; 07.07.2014

Возможно, вы захотите научиться использовать 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 с любым годом и месяцем, которые вы хотите.

person daotoad    schedule 03.07.2014
comment
Обязательно установлю модуль спасибо! :) Будет хорошо проверить код наверняка. - person John; 03.07.2014

Мне нравится perl, но для этой базовой функции я использовал ротацию журналов с cron.

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

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

person user3803830    schedule 04.07.2014
comment
Добро пожаловать в StackOverflow! Было бы полезно, если бы вы разместили соответствующие цитаты из своих ссылок в своем ответе, чтобы пользователям не приходилось их искать. - person hmatt1; 04.07.2014