(PERL) Запуск скрипта из скрипта и получение параметров

Yevgen
Дата: 31.08.2006 15:18:31
Подскажите пожалуйста, как можно решить такую проблему. Значит, имеется объект. У него множество команд с различными параметрами. Запускаются они на выполнение через один метод command(command_code, params). Выглядит это примерно так:

$object->command(cc=>0x01, param1=>1, param2=>'write',..., paramn=>n)

Теперь сама суть вопроса. Нужно последовательно перебрать все возможные команды с параметрами. Но проблема в том, как сформировать вызов метода command не только со значениями параметров, но и с их мнемониками "cc", "param1"..."paramn". Плюс ко всему, число параметров нефиксированное.

Я вижу только один вариант - генерировать в моем скропте еще один скриптовый файл, который будет и вызываться следом. Но вот проблема - как получить результаты выполнения этой команды? Результатов обычно 2:

($res1, $res2) = $object->command(cc=>0x01, param1=>1, param2=>'write',..., paramn=>n)

Причем это, как правило, указатели на хэши. Как можно из скрипта получить результат, не записывая куда-то в файл?

И второй вопрос: может кто-нибудь подскажет более оптимальный и красивый вариант? Буду очень благодарен.

Заранее спасибо!
Black
Дата: 31.08.2006 15:50:38
$object->command( { cc => 0x01, param1 => 1, param2 => 'write',..., paramn => n } )

sub commant
{
	my %parameters = @_;
}

Yevgen
У него множество команд с различными параметрами.

Это называется параметры и их значения.
Yevgen
Дата: 31.08.2006 16:06:21
Николай aka Motodor
$object->command( { cc => 0x01, param1 => 1, param2 => 'write',..., paramn => n } )

sub commant
{
	my %parameters = @_;
}

Yevgen
У него множество команд с различными параметрами.

Это называется параметры и их значения.


Николай, спасибо за такой быстрый ответ, но к сожалению вы меня неправильно поняли. Метод command уже есть и переписывать мне его не нужно. Мне необходимо его вызвать, но вызвать не с какими-то определенными значениями параметров, и даже с различными параметрами. У меня есть список кодов команд и список параметров для каждой команды. Т.е. у меня в цыкле будет перебираться хэш с командами, где каждый элемент содержит, например, код команды и список параметров, как-то:

\%cmd_hash
     ->{Command1}
             ->{cc}=0x01
             ->{list_of_params}
                   ->{c1_param1}=1
                   ->{c1_param2}=2
     ->{Command2}
             ->{cc}=0x02
             ->{list_of_params}
                   ->{c2_param1}='write'
                   ->{c2_param2}=15
                   ->{c2_param3}='lock'

          ...

Далее в каждой итерации будет извлекаться информация по каждой команде, и на основе нее будет формироваться запрос на выполнение команды:
Итерация 1: $object->command(cc=>0x01, c1_param1=>1, c1_param2=>2);
Итерация 2: $object->command(cc=>0x02, c2_param1=>'write', c2_param2=>15, c2_param3='lock');
         ...

Так вот, каким же образом мне динамически формировать на каждой итерации вызов метода command, чтобы туда передавались и нужные имена мнемоник команд, и, также, нужные значения. Есть вариант, на каждой итерации формировать файл, который будет содержать объявление объекта $object и вызов уже сгенерированного в текстовом виде метода и его входных параметров. Но тогда как получить результат, чтобы не сохранять его в файл? Или, может быть, есть другой вариант, которого я не знаю? Подскажите пожалуйста.
Black
Дата: 31.08.2006 16:12:43
perldoc eval

eval EXPR
eval BLOCK
In the first form, the return value of EXPR is parsed and
executed as if it were a little Perl program. The value of the
expression (which is itself determined within scalar context) is
first parsed, and if there weren't any errors, executed in the
lexical context of the current Perl program, so that any
variable settings or subroutine and format definitions remain
afterwards. Note that the value is parsed every time the eval
executes. If EXPR is omitted, evaluates $_. This form is
typically used to delay parsing and subsequent execution of the
text of EXPR until run time.

In the second form, the code within the BLOCK is parsed only
once--at the same time the code surrounding the eval itself was
parsed--and executed within the context of the current Perl
program. This form is typically used to trap exceptions more
efficiently than the first (see below), while also providing the
benefit of checking the code within BLOCK at compile time.

The final semicolon, if any, may be omitted from the value of
EXPR or within the BLOCK.

In both forms, the value returned is the value of the last
expression evaluated inside the mini-program; a return statement
may be also used, just as with subroutines. The expression
providing the return value is evaluated in void, scalar, or list
context, depending on the context of the eval itself. See
"wantarray" for more on how the evaluation context can be
determined.

If there is a syntax error or runtime error, or a "die"
statement is executed, an undefined value is returned by "eval",
and $@ is set to the error message. If there was no error, $@ is
guaranteed to be a null string. Beware that using "eval" neither
silences perl from printing warnings to STDERR, nor does it
stuff the text of warning messages into $@. To do either of
those, you have to use the $SIG{__WARN__} facility, or turn off
warnings inside the BLOCK or EXPR using "no warnings 'all'". See
"warn", perlvar, warnings and perllexwarn.

Note that, because "eval" traps otherwise-fatal errors, it is
useful for determining whether a particular feature (such as
"socket" or "symlink") is implemented. It is also Perl's
exception trapping mechanism, where the die operator is used to
raise exceptions.

If the code to be executed doesn't vary, you may use the
eval-BLOCK form to trap run-time errors without incurring the
penalty of recompiling each time. The error, if any, is still
returned in $@. Examples:

# make divide-by-zero nonfatal
eval { $answer = $a / $b; }; warn $@ if $@;

# same thing, but less efficient
eval '$answer = $a / $b'; warn $@ if $@;

# a compile-time error
eval { $answer = }; # WRONG

# a run-time error
eval '$answer ='; # sets $@

Due to the current arguably broken state of "__DIE__" hooks,
when using the "eval{}" form as an exception trap in libraries,
you may wish not to trigger any "__DIE__" hooks that user code
may have installed. You can use the "local $SIG{__DIE__}"
construct for this purpose, as shown in this example:

# a very private exception trap for divide-by-zero
eval { local $SIG{'__DIE__'}; $answer = $a / $b; };
warn $@ if $@;

This is especially significant, given that "__DIE__" hooks can
call "die" again, which has the effect of changing their error
messages:

# __DIE__ hooks may modify error messages
{
local $SIG{'__DIE__'} =
sub { (my $x = $_[0]) =~ s/foo/bar/g; die $x };
eval { die "foo lives here" };
print $@ if $@; # prints "bar lives here"
}

Because this promotes action at a distance, this
counterintuitive behavior may be fixed in a future release.

With an "eval", you should be especially careful to remember
what's being looked at when:

eval $x; # CASE 1
eval "$x"; # CASE 2

eval '$x'; # CASE 3
eval { $x }; # CASE 4

eval "\$$x++"; # CASE 5
$$x++; # CASE 6

Cases 1 and 2 above behave identically: they run the code
contained in the variable $x. (Although case 2 has misleading
double quotes making the reader wonder what else might be
happening (nothing is).) Cases 3 and 4 likewise behave in the
same way: they run the code '$x', which does nothing but return
the value of $x. (Case 4 is preferred for purely visual reasons,
but it also has the advantage of compiling at compile-time
instead of at run-time.) Case 5 is a place where normally you
*would* like to use double quotes, except that in this
particular situation, you can just use symbolic references
instead, as in case 6.

"eval BLOCK" does *not* count as a loop, so the loop control
statements "next", "last", or "redo" cannot be used to leave or
restart the block.

Note that as a very special case, an "eval ''" executed within
the "DB" package doesn't see the usual surrounding lexical
scope, but rather the scope of the first non-DB piece of code
that called it. You don't normally need to worry about this
unless you are writing a Perl debugger.
nik2
Дата: 31.08.2006 16:27:04
Yevgen
Николай aka Motodor
$object->command( { cc => 0x01, param1 => 1, param2 => 'write',..., paramn => n } )

sub commant
{
	my %parameters = @_;
}

Yevgen
У него множество команд с различными параметрами.

Это называется параметры и их значения.


Николай, спасибо за такой быстрый ответ, но к сожалению вы меня неправильно поняли. Метод command уже есть и переписывать мне его не нужно. Мне необходимо его вызвать, но вызвать не с какими-то определенными значениями параметров, и даже с различными параметрами. У меня есть список кодов команд и список параметров для каждой команды. Т.е. у меня в цыкле будет перебираться хэш с командами, где каждый элемент содержит, например, код команды и список параметров, как-то:

\%cmd_hash
     ->{Command1}
             ->{cc}=0x01
             ->{list_of_params}
                   ->{c1_param1}=1
                   ->{c1_param2}=2
     ->{Command2}
             ->{cc}=0x02
             ->{list_of_params}
                   ->{c2_param1}='write'
                   ->{c2_param2}=15
                   ->{c2_param3}='lock'

          ...

Далее в каждой итерации будет извлекаться информация по каждой команде, и на основе нее будет формироваться запрос на выполнение команды:
Итерация 1: $object->command(cc=>0x01, c1_param1=>1, c1_param2=>2);
Итерация 2: $object->command(cc=>0x02, c2_param1=>'write', c2_param2=>15, c2_param3='lock');
         ...

Так вот, каким же образом мне динамически формировать на каждой итерации вызов метода command, чтобы туда передавались и нужные имена мнемоник команд, и, также, нужные значения. Есть вариант, на каждой итерации формировать файл, который будет содержать объявление объекта $object и вызов уже сгенерированного в текстовом виде метода и его входных параметров. Но тогда как получить результат, чтобы не сохранять его в файл? Или, может быть, есть другой вариант, которого я не знаю? Подскажите пожалуйста.


my $cmd = {
            com1 => {
                cc => '0x01',
                list_of_params => {
                    c1_param    => 1,
                    c1_param2   => 2,
                }
            },
            com2 => {
                cc => '0x02',
                list_of_params => {
                    c2_param    => 3,
                    c2_param2   => 4,
                }
            }
    };

foreach my $key ( keys %{$cmd} ) {
#   print "cc=>",$cmd->{$key}->{cc}, ',', join(',',%{$cmd->{$key}->{list_of_params}});
#   print "\n";
    $object->command(cc=>$cmd->{$key}->{'cc'}, (%{$cmd->{$key}->{list_of_params}}) )
}



nik2
Дата: 31.08.2006 16:30:45
P.S.

sort к foreach предлагается прикрутить самому если порядок следования команд важен...
Yevgen
Дата: 31.08.2006 16:54:02
Спасибо всем за помощь. Теперь разберусь. Оба совета хороши, осталось только выбрать более удобный вариант. Знал бы лично, поставил бы пиво. :)
Black
Дата: 31.08.2006 17:04:42
Yevgen
Спасибо всем за помощь. Теперь разберусь. Оба совета хороши, осталось только выбрать более удобный вариант. Знал бы лично, поставил бы пиво. :)

Используйте лучше вариант предложенный nik2, т.к. я невнимательно прочитал условие, думал, что надо сразу весь хэш обработать зараз ...
Yevgen
Дата: 31.08.2006 19:31:29
Николай aka Motodor
Yevgen
Спасибо всем за помощь. Теперь разберусь. Оба совета хороши, осталось только выбрать более удобный вариант. Знал бы лично, поставил бы пиво. :)

Используйте лучше вариант предложенный nik2, т.к. я невнимательно прочитал условие, думал, что надо сразу весь хэш обработать зараз ...


Ну, я просто посмотрю еще что мне будет удобнее. Я могу формировать для каждой команды отдельный хэш с параметрами, которые используются. Но мне, возможно, понадобится перехватывать сообщения с корбовскими исключениями или не вылетать по die, потому придется использовать eval. Возможно придумаю комбинацию и того, и другого.
Anjey aka PM
Дата: 01.09.2006 00:12:19
Yevgen
Но мне, возможно, понадобится перехватывать сообщения с корбовскими исключениями или не вылетать по die


вот красивый java-style класс