Как правильно вызвать sub, ссылаясь на perl? - PullRequest
1 голос
/ 29 декабря 2011

Я работаю над диспетчерским сценарием, он берет строку с командой, готовит и обрабатывает ее. Но я не могу ухватиться за ссылки:

Use::strict;
Use:warnings;

my($contexto,$cmd,$target,$ultpos,@params);
my $do= "echo5 sample string that says stuff ";

$target="";
$cmd="";
$_="";
# i do some cumbersome string parsing to get the array with the exploded string and then call parsear(@command)

sub parsear{

my %operations=(
'echo' => \&echo,
'status' => \&status,
'echo5' => \&echo5,
);

my $op= $_[0];
if ($operations{$op}){
    $operations{$op}->(@_);
    print "it exists\n";
}else{
    print "incorrect command.\n";
    }
}




sub status{
    print "correct status.\n";
}

sub echo{
    shift(@_);
    print join(' ',@_) . "\n";
}

sub echo5{
    shift(@_);
    print join(' ',@_) . "\n" x 5;
}

Я действительно не знаю, в чем проблема, если подпрограмма не существует, она никогда не говорит «неверная команда», и если я назову, например, «echo5 hello», она должна распечатать

hello
hello
hello
hello
hello

но ничего не делает.

И когда я вызываю эхо, оно работает как положено. Может кто-нибудь объяснить мне это волшебство? примечание: я на последней версии клубничного Perl

Ответы [ 2 ]

2 голосов
/ 29 декабря 2011
use strict;  # use is a keyword
use warnings;

# all these variables are not needed

sub parsear {  # learn to indent correctly
    my %operations = (
        'echo'   => \&echo,
        'status' => \&status,
        'echo5'  => \&echo5,
    );
    my $op = shift;  # take first element off @_
    if ($operations{$op}) {
        print "$op exists\n";  # make your status msg useful
        $operations{$op}->(@_);
    } else {
        print "incorrect command: $op\n";  # and your error msg
    }
}    

sub status {
    print "correct status.\n";
}

sub echo {
    # shift(@_); # this is no longer needed, and now echo can be used as a
                 # normal subroutine as well as a dispatch target
    print join(' ',@_) . "\n";
}

sub echo5 {
    # shift(@_); # this is no longer needed
    print +(join(' ',@_) . "\n") x 5;  # parens needed since x binds tightly
}

затем выполняется:

parsear 'status';
parsear 'echo', 'hello';
parsear 'echo5', 'hello';
parsear 'an error';

приводит к:

status exists
correct status.
echo exists
hello
echo5 exists
hello
hello
hello
hello
hello
incorrect command: an error

Я не уверен, что cumbersome string parsing вы делаете, поскольку вы его не включили, но есливы анализируете строку типа

my $do = "echo5 sample string that says stuff ";

, где команда является первым словом, а аргументы - остальными, вы можете либо разбить все:

parsear split /\s+/, $do;

или использовать регулярное выражение дляобрежьте первое слово:

my ($cmd, $arg) = $do =~ /^(\w+)\s*(.*)/;

parsear $cmd => $arg;

вам даже не нужны переменные:

parsear $do =~ /^(\w+)\s*(.*)/;

наконец, подпрограмма echo5 немного сложнее, чем нужнобыть.Это может быть записано как:

sub echo5 {
    print "@_\n" x 5;  # "@_" means join($", @_) and $" defaults to ' '
}
0 голосов
/ 29 декабря 2011

Команда x связывается не так, как вы ожидали; Вы, вероятно, хотели:

print ((join(' ', @_) . "\n") x 5);

Оба дополнительных набора скобок казались необходимыми.

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