Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

comment on

( [id://3333]=superdoc: print w/replies, xml ) Need Help??

I've got a requirement to be able to pass a command and its arguments to exec() in indirect object notation (perldoc -f exec). As documented (if I'm understanding correctly), the indirect object syntax avoids the shell, and returns nothing, which is exactly what I need it to do. An example of the syntax would be (according to perldoc):

exec { $command } @args

I have my input command and its arguments tucked away as a single string in a database row value. An example would look like this:

/usr/local/bin/ssh %s '/opt/something/bin/somebinary || echo "Could not execute somebinary.  Confirm that the host has FOO attached and try running somebinary manually on the host to troubleshoot"'

It's not my database, so I don't get to choose or change how commands and arguments are stored. This is what I have to work with. So I have to figure out how to split up that line intelligently, whether in one pass or more, so that my command and its arguments are passed to exec exactly (or as close to it) as they would be if the command was typed into a console.

I seek the wisdom of the Perl Monks in this endeavor... The solution has to be robust enough that it is fool-proof as possible; literally, robust enough to cover the corner cases that joe user may put into the database. My idea so far looks like this (and it doesn't work because it doesn't preserve the order of the arguments). The unpolished nature of this solution is frankly embarrassing to post, and given enough time I could work this out on my own but it looks like a fun thought exercise. Not fully tested:

my ( $command, $argstring ) = split / /, $string, 2; # single-quoted args like 'red wagon' my ( @args ) = $argstring =~ s/[[:space:]]+'(.*?)'//g; # double-quoted args, where the closing quote isn't preceded by "\" push @args, $argstring =~ s/[[:space:]]+"(.*?[^\]*)"//g; # args that aren't quoted at all, like --verbose push @args, split / /, $argstring;

Now as I said, this doesn't preserve the order of args. It also falls on its face if the arg is something like --fullname="Tommy Butler". It also doesn't work for quoted strings within quoted strings. I thought of trying to use Getopt::Long, but it doesn't help me when my command looks like the example I provided above.

Suggestions? TIA!

UPDATE:

This shows promise: https://metacpan.org/pod/Argv -- but it's so complex that it seems like total overkill for my needs. This is just a series of simple splits and/or regexen.

UPDATE 2

I've come up with this (code removed cuz it wuz broked) at the suggestion of kennethk. I haven't been able to break it so far. Can you?

UPDATE 3

ARGGGG I just got it to break on my own test scenario of --name="tommy butler". back to the drawing board.

UPDATE 4

This one works: GIST -- previous broken code removed from post. It turns out Eily was right; it was a harder problem than I thought. Post facto: If I knew how to pull matches out of a regex within the regex itself and later on in the regex match based on the previous inner capture, I could eliminate the nested if/else on lines 40 thru 49, but I'll work on that later. Thanks everyone!

Tommy
A mistake can be valuable or costly, depending on how faithfully you pursue correction

In reply to Splitting up quoted/escaped command line arguments by Tommy

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":



  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or How to display code and escape characters are good places to start.
Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others learning in the Monastery: (3)
As of 2024-03-29 02:02 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found