Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?

Mimicking Unix shell quoting in Perl

by eyepopslikeamosquito (Chancellor)
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?

Replies are listed 'Best First'.
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 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;
Re: Mimicking Unix shell quoting in Perl
by djerius (Beadle) on Aug 20, 2007 at 14:48 UTC

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 drinking their drinks and smoking their pipes about the Monastery: (6)
As of 2016-10-20 21:59 GMT
Find Nodes?
    Voting Booth?
    How many different varieties (color, size, etc) of socks do you have in your sock drawer?

    Results (283 votes). Check out past polls.