Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > How to break a bash command into an array consisting of the argumentsin the command?

Reply
Thread Tools

How to break a bash command into an array consisting of the argumentsin the command?

 
 
Peng Yu
Guest
Posts: n/a
 
      05-12-2013
Hi,

Suppose that I have a bash command in a string, e.g.

cmd.sh a 'a b' '
'

I want get an array consisting of "cmd.sh" "a" "a b" "\n". Is there a robust way to do so in perl that can handle all the possible cases? Thanks.
 
Reply With Quote
 
 
 
 
Jürgen Exner
Guest
Posts: n/a
 
      05-12-2013
Peng Yu <(E-Mail Removed)> wrote:
>Suppose that I have a bash command in a string, e.g.
>
>cmd.sh a 'a b' '
>'
>
>I want get an array consisting of "cmd.sh" "a" "a b" "\n". Is there a robust way to do so in perl that can handle all the possible cases? Thanks.


A brief glance at a BASH EBNF shows:

<command> ::= <simple_command>
| <shell_command>
| <shell_command> <redirection_list>

<shell_command> ::= <for_command>
| <case_command>
| while <compound_list> do <compound_list> done
| until <compound_list> do <compound_list> done
| <select_command>
| <if_command>
| <subshell>
| <group_command>
| <function_def>

Somewhat simplified: a command can be rather complex, in particular it
can be recursive and it can contain pretty much any BASH element
whatsoever. And that implies that the answer to your question is:
Of course there is a robust way to write a fully-featured BASH-parser in
Perl. And nothing short of a fully-featured BASH-parser will be able to
parse a BASH command line.

jue
 
Reply With Quote
 
 
 
 
Rainer Weikusat
Guest
Posts: n/a
 
      05-12-2013
Peng Yu <(E-Mail Removed)> writes:
> Suppose that I have a bash command in a string, e.g.
>
> cmd.sh a 'a b' '
> '
>
> I want get an array consisting of "cmd.sh" "a" "a b" "\n". Is there
> a robust way to do so in perl that can handle all the possible
> cases? Thanks.


Do you consider command substitution a possible case? And what about
process substitution? In case process substitution isn't needed, a
reasonably simple idea would be to invoke the shell to let it perform
"word-splitting" on the command string and use perl to transport the
result of that to a 'parent perl' with the help of some 'suitable
encoding', eg

--------------------
sub shell_cmd_to_list
{
my ($all, @l, $one, $pos);

$all = `perl -e 'my \$v; \$v .= pack("Z*", \$_) for \@ARGV; print \$v' $_[0]`;
$pos = 0;
do {
$one = unpack('@'.$pos.'Z*', $all);
push(@l, $one);
$pos += length($one) + 1;
} while ($pos < length($all));

return @l;
}

my $cmd = "a 'a b' 'a\nb' \"`ls /`\"";
my @v = shell_cmd_to_list($cmd);

printf("%u\n--\n%s\n\n", $_, $v[$_]) for (0 .. $#v);
 
Reply With Quote
 
Rainer Weikusat
Guest
Posts: n/a
 
      05-13-2013
Rainer Weikusat <(E-Mail Removed)> writes:
> Peng Yu <(E-Mail Removed)> writes:
>> Suppose that I have a bash command in a string, e.g.
>>
>> cmd.sh a 'a b' '
>> '
>>
>> I want get an array consisting of "cmd.sh" "a" "a b" "\n". Is there
>> a robust way to do so in perl that can handle all the possible
>> cases?


[...]

> sub shell_cmd_to_list
> {
> my ($all, @l, $one, $pos);
>
> $all = `perl -e 'my \$v; \$v .= pack("Z*", \$_) for \@ARGV; print \$v' $_[0]`;
> $pos = 0;
> do {
> $one = unpack('@'.$pos.'Z*', $all);
> push(@l, $one);
> $pos += length($one) + 1;
> } while ($pos < length($all));
>
> return @l;
> }


Coming to think of this, this should probably rather be

----------------
sub shell_cmd_to_list
{
my ($all, @l, $one, $pos);

$all = `perl -e 'my \$v; \$v .= pack("Z*", \$_) for \@ARGV; print \$v' $_[0]`;
$? and return ();

$pos = 0;
while ($pos < length($all)) {
$one = unpack('@'.$pos.'Z*', $all);
push(@l, $one);
$pos += length($one) + 1;
}

return @l;
}
-----------------

which will return an empty list in case the shell encountered a synax
error in the argument string (alternatively, an exception could be
thrown) or if there were no arguments.

It should also be noted that this will not only perform command
substitution aka 'run arbitrary commands contained in the argument
string' but will also run an arbitrary 'trailing shell script'
attached to $_[0], IOW, it is completely unsuitable for processing
input from untrusted sources. OTOH, the shell already knows how to
parse 'shell commands' and using it to do this instead of
reprogramming the parser in Perl is IMHO generally sensible.

Special note: This is one of the rare cases where initializing a
variable is actually necessary in Perl because '@Z*' is not the same
as '@0Z*'.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Windows 8 - so bad it's hastening the death of the PC? ~misfit~ NZ Computing 18 04-15-2013 04:15 AM
How to move text within Jlabels to the right clusardi2k@aol.com Java 6 04-13-2013 07:20 PM
silly question about Running a script from the command line A.Rock Python 0 04-10-2013 11:21 AM
Re: How include a large array? Edward A. Falk C Programming 1 04-04-2013 08:07 PM
(patch for Bash) GTK+2 + Bash William Park XML 3 07-14-2005 12:09 AM



Advertisments