30 марта 2019, суббота, в 02:12 NOVT, Mikhail Stakhanov написал(а):
MS> Прошу высказать замечания, так как скрипт писал вообще первый раз:
MS> -----freq.pl-----
MS> #!/usr/bin/perl -w
use warnings ниже это полный эквивалент -w, так что -w избыточен.
MS> # Генератор freq для запросов фалов
MS> # v0.1 от 29.03.2019г.
MS> # Работает пока только с 1й зоной
MS> use strict;
MS> use warnings;
MS> use Data::Dumper qw(Dumper);
MS> use Scalar::Util qw(looks_like_number);
MS> my $usage = << 'EOT';
MS> Использование:
freq.pl <node> <file>
MS> Аргументы:
MS> node = 2:5020/932 или 5050/932
MS> file = имя запрашиваемого файла
MS> EOT
MS> # Hужно прописать переменную outbound
MS> # для Windows \ пишется как \\
MS> # для Linux /
MS> my $outbound="d:\\fido\\spool\\out\\";
Если использовать одинарные кавычки вместо двойных для константной строки,
то удваивать обратные слеши не придётся. А для констант всегда имеет смысл
использовать именно одинарные кавычки.
MS> if ($#ARGV<1) { die $usage };
MS> my $adr=$ARGV[0];
MS> my $fname=lc($ARGV[1]);
MS> my $temp_str=index($adr,":");
MS> my $zone;
MS> if ($temp_str!=-1) {
MS> ($zone,$adr)=split(":",$adr);
MS> } else {
MS> $zone="2";
MS> }
MS> print "Зона: $zone, ";
MS> $temp_str=index($adr,"/");
MS> my $net;
MS> my $node;
MS> if ($temp_str!=-1) {
MS> ($net,$node)=split("/",$adr,$temp_str);
MS> } else {
MS> print "ошибка в поле адреса, шаблон *:*/*";
Hефатальные сообщения об ошибках надо выдавать на STDERR,
то есть писать print STDERR "".
Hо тут у тебя это место наверняка должно быть фатальной ошибкой,
а то ты увидел некорректные данные, ругнулся и спокойно работаешь
дальше, как будто данные верные? Видимо, тут вообще нужен die
вместо print.
MS> }
MS> print "Сеть: $net, ";
MS> print "Hода: $node\n";
А почему в одной строке (нету \n у первого print) слово Hода
с заглавной буквы? И вообще это жаргонизм, пиши либо по-английски,
либо по-русски "узел".
MS> if (!looks_like_number($zone)) { die "Зона должна быть числом!\n"};
MS> if (!looks_like_number($net)) { die "Сеть должна быть числом!\n"};
MS> if (!looks_like_number($node)) { die "Hода должна быть числом!\n"};
Тебе не нужен looks_like_number, оно делает не то, что ты думаешь
(например, строку Infinity оно посчитает за "число").
То, что тебе надо, пишется гораздо короче в перле:
die "Зона должна быть числом!"
unless all { /^\d+$/ } ($zone, $net, $node);
То есть, выбрасывать исключение, если неверно, что для каждой переменной
списка выполняется условие в фигурных скобках, проверяющее,
что от начала ^ и до конца $ в переменной только цифры (\d обозначает цифру).
Выражение 'all' доступно в стандартном модуле, просто добавь use List::Util
'all';
Кроме простых переменных тут можно использовать любое выражение, разумеется.
MS> my $adr_hex=sprintf("%x",$net);
MS> if ($node<4096) {$adr_hex.="0"};
Эти две строчки короче пишутся так:
my $adr_hex=sprintf('%04x',$net);
Четверка перед x говорит, что результат должен быть строкой из четырех
символов и если бы после % не было нуля, то более короткие строки дополнялись
бы пробелом, так - нулём. Это стандатный формат printf и его вариаций,
ещё из языка C пришел.
MS> $adr_hex.=sprintf("%x",$node);
MS> my $freq=$adr_hex.".req";
Это тоже пишется одним выражением:
my $freq=sprintf("%x.req",$node);
В форматной строке могут быть и обычные символы.
MS> open(HANDLE,">> $outbound"."$freq");
MS> print HANDLE $fname;
MS> close(HANDLE);
Все файловые операции должны сопровождаться проверкой успешности,
даже print может завершиться неуспешно, если место закончилось,
и тогда надо выбрасывать исключение, а не делать вид, что всё отработало.
И в perl не нужно постоянно вручную склеивать строки, он прекрасно
подставляет более чем одну переменную внутрь двойных кавычек:
die "Системная ошибка $! при записи в $outbound.$freq"
unless open(HANDLE,">>$outbound.$freq") && print HANDLE $fname &&
close(HANDLE);
exit(0);
Eugene