简体   繁体   中英

How to interpret a string as command to execute with parameters in perl

Trying to find an equivalent solution for below in perl. Suppose I have the following POSIX shell script:

#!/bin/sh

MY_CMD='WDT=$1; shift ; printf "%-${WDT}.${WDT}s\n" "$@"'
eval $MY_CMD

An suppose that above is being saved as my_script.sh

And if I execute it like: ./my_script.sh 4 Hello to thise nice girls then the output will be like:

Hell
to
this
nice
girl

How can I do the same using perl . Here the main problems is how do I take perl input parameters and pass them to my command saved in an variable so that those parameters will get evaluated accordingly to the ones from input (in shell eval does this properly).

Should it be that I asked horribly stupid questions, please excuse me as I just started learning perl .o)

EDIT: I think I need to clarify myself more with the question... I NEED to have the command in a variable. I have simplified the script example here to understand easily the problem. In all solutions so far you are giving me solution how that same task to be done in perl, but please don't focus on the command itself, that is just an example:

Other Examples would be: MY_CMD='export AWKNUMF="%.2f"; exe 93 "$1" "$2" "$3" $(shift 3; echo "$@") | sort -k1,1 | exe 93 ":" 1 2' MY_CMD='export AWKNUMF="%.2f"; exe 93 "$1" "$2" "$3" $(shift 3; echo "$@") | sort -k1,1 | exe 93 ":" 1 2'

and so on...

The idea that MY_CMD variable would be populated with some command retrieved from a repository which expects some parameters and I want those parameters to be provided in the input to the perl .

SYNOPSYS would be ./perl_script.pl my_command_name [param1 [param2 ... [paramN]]]

The point here is that you should not focus on the content of the MY_CMD variable. It is just a shell command(s) which gets parameters along.

the perl equivalent would be something like:

system ($my_cmd, "@ARGV"); but this of course does not work as expected.

No eval needed in Perl (I doubt it's needed in the shell, either).

#!/usr/bin/perl
use warnings;
use strict;

my $width = shift;
printf "%-$width.${width}s\n", $_ for @ARGV;

There's two elements to your request.

Firstly - perl uses @ARGV to hold command line parameters. You can access individual elements either with shift or $ARGV[1] .

Secondly - eval works in perl too - but you'll probably find there's a better way of doing what you're trying to do.

So to take your example:

#!/usr/bin/perl
use strict;
use warnings;

my ( $WDT, @words ) = @ARGV; 

foreach my $word ( @words ) {
   printf ( "%-${WDT}.${WDT}s\n", $word );
}

How can I do the same using perl .

Perl too has the eval() function . It can take a string and evaluate it in the context it was called from.

Here the main problems is how do I take perl input parameters and pass them to my command saved in an variable so that those parameters will get evaluated accordingly to the ones from input (in shell eval does this properly).

You have to create the variables before the eval 'ed Perl code can access. That also would, depending on the implementation, bypass or conflict directly with the use strict .

I'm away of two way to create the variables: using eval or by creating them by manipulating the symbol table . Consider:

my $value_of_a = 10;
my $value_of_b = 20;

# alt1 : create vars using `eval`
eval '$a = '.$value_of_a;
eval '$b = '.$value_of_b;
eval q{ print "$a + $b = ", $a+$b, "\n"; };

# alt2 : create the vars by manipulating the symbol table directly
$var_name = "aa";
${"::$var_name"} = $value_of_a;
$var_name = "bb";
${"::$var_name"} = $value_of_b;
eval q{ print "$aa + $bb = ", $aa+$bb, "\n"; };

To avoid calling the eval every time to interpret the code, one can also try to wrap the code into a nameless function and eval it once to create the subroutine which can be called at any time. Consider:

# the input data:
my $var_name_a = 'a';
my $var_name_b = 'b';
my $value_of_a = 10;
my $value_of_b = 20;
my $cmd = 'print "$a + $b = ", $a+$b, "\n";';

# the preparations:
eval '$'.$var_name_a.' = '.$value_of_a;
eval '$'.$var_name_b.' = '.$value_of_b;
my $sub = eval 'sub { '. $cmd .' }';

# the execution:
$sub->();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM