Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much
 
PerlMonks  

Scalar to @ARGV for Getopt::Std

by c64whiz (Initiate)
on May 19, 2016 at 03:43 UTC ( [id://1163407]=perlquestion: print w/replies, xml ) Need Help??

c64whiz has asked for the wisdom of the Perl Monks concerning the following question:

I want to have Getopt::Std parse a "command line" for me, but the "command line" is coming from STDIN. I've done a simple "split /\s+/" to @ARGV, but that doesn't account for parameters with spaces surrounded by quotes:

use Getopt::Std; ## This works in general $cmdline = '-a b -c d'; @ARGV = split /\s+/, $cmdline; getopts( "a:c:" ); ### ...but this obviously fails: $cmdline = '-a "hello world" -b "some \"text\""';

The quoting and escaping is typically done by the *shell*. Any ideas to turn a scalar into an array for @ARGV? Using modules is OK provided they're part of the standard Perl distro; adding modules is not an option. Google's not being helpful.

Thanks!

Replies are listed 'Best First'.
Re: Scalar to @ARGV for Getopt::Std
by haukex (Archbishop) on May 19, 2016 at 07:19 UTC

    Hi c64whiz,

    Some shells have ludicrously complex quoting/interpolation rules, so personally I'd avoid trying to re-implement them. If you really wanted to implement a simple subset of them though, there's Text::ParseWords, this is what Getopt::Long's GetOptionsFromString uses.

    But I have the same question afoken already asked: why are you getting the command line on STDIN?

    Here is a possible solution for applying getopts to a string:

    use warnings; use strict; =head2 getopts_from_str(string, argumentspec, hashref) This function uses L<Text::ParseWords>'s C<shellwords> to parse the given I<string>, and then applies C<getopts> from L<Getopt::Std> to the result, passing it the I<argumentspec> and I<hashref>. If C<getopts> returns a true value, this function returns an arrayref of the arguments remaining after applying C<getopts>, and if C<getopts> reports an error by returning false, this function also returns false. =cut use Text::ParseWords 'shellwords'; use Getopt::Std 'getopts'; sub getopts_from_str { my ($str,$argspec,$hashref) = @_; local @ARGV = shellwords($str); return unless getopts($argspec, $hashref); return [@ARGV]; } # Example Code: my $optstr = q{ -a "hello world" -b "some \"text\"" -c 'abc def' }; my $argv = getopts_from_str($optstr, 'a:b:c', \my %opts) or die "bad options"; use Data::Dumper; print Dumper(\%opts, $argv); __END__ $VAR1 = { 'b' => 'some "text"', 'a' => 'hello world', 'c' => 1 }; $VAR2 = [ 'abc def' ];

    Update 2016-12-20: Since I've linked to this node a few times, I updated the above code so that it provides the function getopts_from_str. The original code follows.

    Hope this helps,
    -- Hauke D

      I can answer part of the "why". (Probably not the OP's reason, though.)

      A number of standard tools also take options from environment variables. E.g. less, gzip. This is a dubious practice, for sure. Less instructs the user to terminate any string args with a dollar sign '$' in that case. Gzip's handling of environment is still broken AFAIK was broken1). (It'll gladly read filenames, not just arguments—to a very comical effect when "GZIP=/bin/gzip" happens to be the case.)

      The problem may also arise from attempting to bypass shell invocation for whatever reason.

      1) Correction: this seems to be fixed in gzip version 1.7.

Re: Scalar to @ARGV for Getopt::Std
by NetWallah (Canon) on May 19, 2016 at 04:53 UTC
    You may be over-thinking this.

    "getopt" will split @argv for you, and do the right thing.

    perl -MGetopt::Std -E 'getopts("oif:"); say $_,"=",${"opt_$_"} for qw +|o i f|' -- -o -f this o=1 i= f=this

            This is not an optical illusion, it just looks like one.

Re: Scalar to @ARGV for Getopt::Std
by afoken (Chancellor) on May 19, 2016 at 06:08 UTC
    I want to have Getopt::Std parse a "command line" for me, but the "command line" is coming from STDIN.

    Why? Usually, the shell (Unix, cygwin) or the C runtime (Windows, DOS, OS/2) handles command line parsing.

    Alexander

    --
    Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1163407]
Approved by davido
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others contemplating the Monastery: (7)
As of 2024-04-19 07:36 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found