Простой Perl Script: два вопроса - PullRequest
2 голосов
/ 21 февраля 2010

У меня есть небольшая программа:

#!/user/bin/perl

use strict;
system ("clear");
my($option, $path);

do
{
    print "\tEnter the number of your chosen option:\n";    
    print "\n";
    print "\tOption\t\tCommand\n";
    print "\t======\t\t=======\n";
    print "\t1\t\tDate\n";
    print "\t2\t\tDirectory Listing\n";
    print "\t3\t\tCalendar\n";
    print "\t4\t\tVi Editor\n";
    print "\t5\t\tCalculator\n";
    print "\t6\t\tExit\n\n";
    chomp($option=<STDIN>);

    SWITCH:
    {
        ($option =="1") and do
        {
            system(date);           
            last;
        };

        ($option =="2") and do
        {
            print "Enter the path:"; ############################
            chomp($path=<STDIN>);    #This is giving me an error#
            system(ls $path);        ############################
            last;
        };  

        ($option =="3") and do
        {
            system(cal);
            last;
        };

        ($option =="4") and do
        {
            system(vi);
            last;
        };

        ($option =="5") and do
        {
            system(bc);
            last;
        };      
    }   
}while ($option!=6);

print "Goodbye!\n";
sleep 2;

Первый вопрос: Может ли кто-нибудь помочь мне написать правильную команду для создания списка каталогов в случае 2.

Второй вопрос: почему я получаю цикл, если использую

$date = `date`;
print "$date"; 

вместо

system(date);

Ответы [ 5 ]

3 голосов
/ 21 февраля 2010

Вы должны быть в состоянии решить большинство своих проблем, не забывая помещать кавычки вокруг буквальных аргументов в system():

system("date");
system("ls $path");

и то же самое для большинства других мест, по которым вы звоните system() (ваш первый звонок на system("clear") правильный).

Причуда Perl в том, что вызов чего-то вроде system(cal) работает вообще, потому что не заключенный в кавычки cal интерпретируется Perl как "голое слово", что примерно соответствует строке при передаче функции такие как system(). Полагаться на такое поведение было бы ужасно плохой практикой, и поэтому вы всегда должны заключать в кавычки буквальные строки.

2 голосов
/ 21 февраля 2010

Вы можете прочитать путь как:

chomp($path=<STDIN>);
system("ls $path");

Не уверен, почему вы получите цикл для $date =date;print "$date";. Но я не думаю, что есть функция date, если вы не используете пакет для нее. Вы можете показать время как:

my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime;
$year += 1900;
$mon += 1;
printf "%04d-%02d-%02d %02d:%02d:%02d", 
       $year, $mday, $mon, 
       $hour, $min, $sec;

В большинстве Unix-систем perl находится в /usr/bin, без e в user, поэтому вы можете подумать о двойной проверке первой строки вашего скрипта.

1 голос
/ 21 февраля 2010

Ваши непосредственные проблемы были вызваны кавычками и отсутствием use warnings в вашем скрипте.

Стоит также отметить, что скрипты на основе меню, подобные вашим, являются идеальными кандидатами для таблиц отправки . Таблица диспетчеризации - это метод определения действий в качестве данных. Действия являются подпрограммами Perl. Данные обычно представляют собой набор пар ключ-значение, которые в конечном итоге сохраняются в хэше.

Ключи хеша - это выбор, сделанный пользователем (пункты меню 1-6 в вашем случае).

Значения в хэше называются ссылками на код. Есть два способа установить эти ссылки на код: (1) непосредственно в таблице диспетчеризации, используя анонимные подпрограммы; или (2) используя синтаксис &\foo, который создаст ссылку на подпрограмму с именем foo.

Удобным в этом подходе является то, что ваш метод menu() можно использовать повторно - просто с другой таблицей отправки и другим сообщением об использовании.

Этот пример настолько мал, что польза от повторного использования может показаться неубедительной, но общий метод получения данных - в форме таблицы диспетчеризации - поведения программы управления является мощным во многих контекстах.

# Always use both of these.
use strict;
use warnings;

sub dispatch_table {
    return
        1 => sub { system 'date' },
        2 => \&ls_path,
        3 => sub { system 'cal'  },
        4 => sub { system 'vi'  },
        5 => sub { system 'bc'  },
        6 => sub { print "Goodbye!\n"; sleep 2 },
    ;
}

sub ls_path {
    print "\nEnter the path: ";
    chomp(my $path=<STDIN>);
    # Note quoting. To be super robust, you would
    # need to escape apostrophes in the path.
    system "ls '$path'";
}

sub usage_message {
    return "Choose wisely:

    Option  Command
    ======  =======
    1       Date
    2       Directory Listing
    3       Calendar
    4       Vi Editor
    5       Calculator
    6       Exit
";
}

sub menu {
    system 'clear';
    my %dt = dispatch_table();
    my $option;
    print usage_message();
    while (1){
        print "> ";
        chomp($option = <STDIN>);
        last if exists $dt{$option};
    }
    $dt{$option}->();
}

menu();
0 голосов
/ 21 февраля 2010

Первая пара предложений, которые у меня есть, во-первых, как и другие уже предложили, use warnings настоятельно рекомендуется. Старые интерпретаторы Perl могут потребовать, чтобы вы использовали старую форму #!/usr/bin/perl -w в качестве первой строки вашего Perl-скрипта. Во-вторых, имеется модуль Switch , чтобы оператор switch выглядел менее уродливо. Я также показал использование подпрограмм для очистки внешнего вида программы.

Я приложил альтернативную версию вашего скрипта с некоторыми потенциальными предложениями. Обратите внимание, что для переключателя используется немного другая альтернатива . Если доступно, я бы рекомендовал использовать модуль Switch. Он включает в себя другой способ печати времени и, конечно, исправляет вашу проблему с системными вызовами.

Надеюсь, это поможет.

#!/usr/bin/perl

use strict;
use warnings;       # otherwise /usr/bin/perl -w in first line

sub menu() {
    print <<EOM;
    Enter the number of your chosen option:

    Option      Command
    ======      =======
    1       Date
    2       Directory Listing
    3       Calendar
    4       Vi Editor
    5       Calculator
    6       Exit
EOM
}

sub showtime() {
    my $time = localtime;
    print $time,"\n";
}

sub listdir() {
    my $path;
    print "Enter the path: ";
    chomp($path = <STDIN>);
    system("ls $path");
    print "\n";
}

system("clear");

my $option;
do {
    menu();
    chomp($option = <STDIN>);

    # SWITCH:
    for ($option) {
        /1/ and do {
            showtime();
        };
        /2/ and do {
            listdir();
        };  
        /3/ and do {
            system("cal");
        };
        /4/ and do {
            system("vi");
        };
        /5/ and do {
            system("bc");
        };
        last;
    }   
} while ($option != 6);

print "Goodbye!\n";
sleep 2;
0 голосов
/ 21 февраля 2010

Я не могу воспроизвести ваш цикл с:

$date =date;print "$date"; 

Я сомневаюсь, что именно так вы и написали, так как я получаю ошибку компиляции с use strict;. Если вы можете показать пример уменьшенного кода, который все еще иллюстрирует проблему, мы могли бы помочь отладить его дальше.

Если вы пытаетесь записать вывод внешней команды в переменную, вы можете использовать обратные метки или qx * ​​1008 *:

my $date = qx(date);
print "$date";

С другой стороны, всякий раз, когда я вижу серию print заявлений, я думаю here-doc :

print <<"EOF";
Enter the number of your chosen option:
    Option Command
    ====== =======
    1      Date
    2      Directory Listing
    etc...
EOF

Немного легче читать и поддерживать, нет?

Наконец, это также хорошая идея для use warnings;.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...