ls -al "file 1" "file'2" ; cat /etc/passwd #### ls '-al' 'file 1' 'file'\''2' ';' 'cat' '/etc/passwd' #### #!/usr/bin/perl # used http://www.cs.hmc.edu/courses/2003/spring/cs60/fsm.pdf # to transform state machine into regexp $cmd=<>; $arg=""; chomp $cmd; $cmd.=" "; # regexp # ( |([^'"\\ ]+)|(\\.)|("(([^"\\])|(\\.))*")|('[^']*')) # only global matching # ( |(?:[^'"\\ ]+)|(?:\\.)|(?:"(?:(?:[^"\\])|(?:\\.))*")|(?:'[^']*')) # we need to do second subst to remove " and ' pairs and unescape \ so need some flags # ( |(?:[^'"\\ ]+)|(\\.)|("(?:(?:[^"\\])|(\\.))*")|('[^']*')) while($cmd=~s/^( |(?:[^'"\\ ]+)|(\\.)|("(?:(?:[^"\\])|(\\.))*")|('[^']*'))(.*)$/$6/) { $c=$1; # the flags... $esc=$2; $dquote=$3; $dquoteEsc=$4; $squote=$5; print "c=$c arg=$arg cmd=$cmd esc=$esc dquote=$dquote dquoteEsc=$dquoteEsc squote=$squote\n"; if($c eq " ") { $arg=~s/'/'\\''/g; # shell escape the ' $res .= "'$arg' "; $arg=""; next; } if(($esc ne "")|($dquoteEsc ne "")) { $c=~s/\\//g } if($dquote ne "") { $c =~ s/^"(.*)"$/$1/} if($squote ne "") { $c =~ s/^'(.*)'$/$1/} $arg .= $c; } print "$res\n";