Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things

Mimicking Unix shell quoting in Perl

by eyepopslikeamosquito (Canon)
on Aug 20, 2007 at 07:33 UTC ( #633728=perlquestion: print w/ replies, xml ) Need Help??
eyepopslikeamosquito has asked for the wisdom of the Perl Monks concerning the following question:

I'd like to be able to mimic the way the Unix shell tokenizes a command line into what a Perl program sees as @ARGV. This little test program hopefully makes clear what I'd like to achieve:

# Mimic the way the Unix shell breaks up cmdline into @ARGV. # Before running this script, create a separate test script,, con +sisting of: # for my $a (@ARGV) { print "a=:$a:\n" } use strict; use warnings; ### $qq matches a single or double quoted string. my $qq = qr/'[^'\\]*(?:\\.[^'\\]*)*'|"[^"\\]*(?:\\.[^"\\]*)*"/; my $cmd = qq{perl arg1 'arg 2' "arg 3" "arg \\"4" arg5}; print "cmd=:$cmd:\n\n"; my @args = $cmd =~ /$qq|\S+/g; for my $t (@args) { if (substr($t, 0, 1) eq "'" || substr($t, 0, 1) eq '"') { $t = substr($t, 1, -1); $t =~ s/\\(['"])/$1/g; } } for my $a (@args) { print "a=:$a:\n" } print "\n"; system($cmd); print "\n"; system { $^X } @args;
Running this program shows that @args above matches what is seen as @ARGV in However, this feels quite tricky and I've got that old re-inventing the wheel feeling. Is there a better way to do this?

Comment on Mimicking Unix shell quoting in Perl
Select or Download Code
Re: Mimicking Unix shell quoting in Perl
by Anonymous Monk on Aug 20, 2007 at 08:04 UTC
      Looking at Shell::Parser leaves me empty inside. It looks like a very lightweight wrapper around lexical analysis. It doesn't appear to do any glob syntax expansion like eyepopslikeamosquito wanted.

      Not only does bash globbing syntax handle foo*.jpg but it deals with foo?.jpg and foo[1-5][xyz].jpg and even foo.{jpg,jpeg} options too. It's a pretty complicated feature, even if you skip all the $VAR interpolation stuff.

      Speaking of which, eyepopslikeamosquito, is it important for your purposes to do things exactly like the shell? Can you assume you're on a platform that actually has the shell, or must you work smoothly on Win/DOS too? You could just shell out a string to xargs, but this is a significant taint-checking exercise too.

      [ e d @ h a l l e y . c c ]

        The Windows shell doesn't do glob. So even a module that doesn't handle globbing can still be much like a "real shell". It just depends on what you use as a role model. :)
Re: Mimicking Unix shell quoting in Perl
by djerius (Beadle) on Aug 20, 2007 at 14:48 UTC
Re: Mimicking Unix shell quoting in Perl
by brx (Pilgrim) on Aug 20, 2007 at 15:39 UTC
    Text::Balanced can probably help you
    use strict; use warnings; use Text::Balanced qw(extract_delimited); my $cmd = qq{perl arg1 'arg 2' "arg 3" "arg \\"4" arg5}; my @tokens; while(length($cmd)){ my $ext = extract_delimited($cmd); if (not defined $ext) { $cmd=~s/^\s*(\S+)\s*//; $ext=$1; } else { ####no delimiters # $ext=substr($ext,1,-1); } push @tokens,$ext; } print join "\n",@tokens;

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://633728]
Approved by Corion
Front-paged by Corion
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others taking refuge in the Monastery: (4)
As of 2014-08-01 01:24 GMT
Find Nodes?
    Voting Booth?

    My favorite superfluous repetitious redundant duplicative phrase is:

    Results (256 votes), past polls