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

#perl #input #command #prompt #localtime

#perl #ввод #команда #запрос #localtime

Вопрос:

Что у меня есть: Чтобы уточнить, в настоящее время у меня есть функция main, которая указывает исходный каталог и каталог архива назначения. В конце каждого месяца данные за прошлый месяц должны быть перемещены в каталог архива. Я все это разобрал, и хорошо, и до конца. Подпрограмма — это то, что выбирает местное время с помощью функции 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 "%dd", $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 moden" : "Regular moden";
  

А затем просто выполните свой скрипт следующим образом, когда вы хотите перейти в тестовый режим:

 perl yourscript.pl --test
  

Комментарии:

1. Если я просто выполняю свой тест, вводя —test в командную строку, как я могу получить доступ к условиям, заданным тестом?

2. Выполнение вашего кода с помощью —test просто устанавливает значение test равным 1?

Ответ №2:

Как сказал Миллер, 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 moden";
} else {
    print "normal moden";
}
  

Попробуйте вызвать с его помощью perl test.pl 0 и perl test.pl 1 .

Комментарии:

1. Я вижу использование Getopts ::Long, но я думаю, что ваше решение лучше всего подходит для моей проблемы. Тем не менее, я играл с этим в течение нескольких дней и не могу понять, как включить входной тестовый аргумент в основную процедуру, одновременно включая условия во вспомогательную процедуру. Я попытался поместить мой $ test = @_; в подпрограмму для вызова моего ввода из функции main, но это не сработало.

2. @_ это массив, и вы вызываете его в скалярном контексте. Попробуйте my ($test) = @_; , и если это не сработает, вы могли бы опубликовать какой-нибудь код и задать другой вопрос.

3. Нет, это не сработало. Я могу заставить его работать идеально, если включу весь ваш код (за вычетом предупреждений use strict и use) в свою подпрограмму, где у меня есть все остальные условия. Но если я попытаюсь использовать часть my $ test = $ ARGV[0]; в основной подпрограмме, она перестанет работать. Вот почему я пытался вызвать его в подпрограмму.

4. @user3799015, мне нужно было бы увидеть ваш код, чтобы разобраться в этом. У вас есть use strict и use warnings в верхней части вашего скрипта, верно? Они указывают на ошибки. Если вы удалите их, ошибки все еще будут, но сообщения не отображаются, и они могут вызвать другие проблемы.

5. Да, я делаю. Код функционирует должным образом, я просто не думаю, что он функционирует совсем так, как я намереваюсь, если я не включу весь код в подпрограмму. Мне только что сказали, что тестирование с помощью подпрограммы — плохая практика.

Ответ №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 specifiedn"
        if (
            ($year amp;amp; !$month)
         || (!$year amp;amp; $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 "dd", $year, $month;
}
  

Вы можете написать тестовый код, который вызывает dateDirectory с любым годом и месяцем, которые вы хотите.

Комментарии:

1. Я обязательно установлю модуль, спасибо! 🙂 Было бы неплохо протестировать код наверняка.

Ответ №4:

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

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

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

Комментарии:

1. Добро пожаловать в StackOverflow! Было бы полезно, если бы вы разместили соответствующие цитаты из ваших ссылок в своем ответе, чтобы пользователям не приходилось их искать.