views:

155

answers:

4

I'm trying to run a perl script from within a bash script (I'll change this design later on, but for now, bear with me). The bash script receives the argument that it will run. The argument to the script is as follows:

test.sh "myscript.pl -g \"Some Example\" -n 1 -p 45"

within the bash script, I simple run the argument that was passed:

#!/bin/sh

$1

However, in my perl script the -g argument only gets "Some (that's with the quotes), instead of the Some Example. Even if I quote it, it cuts off because of the whitespace.

I tried escaping the whitespace, but it doesn't work... any ideas?

+2  A: 

To run it as posted test.sh "myscript.pl -g \"Some Example\" -n 1 -p 45" do this:

#!/bin/bash
eval "$1"

This causes the $1 argument to be parsed by the shell so the individual words will be broken up and the quotes removed.

Or if you want you could remove the quotes and run test.sh myscript.pl -g "Some Example" -n 1 -p 45 if you changed your script to:

#!/bin/bash
"$@"

The "$@" gets replaced by all the arguments $1, $2, etc., as many as were passed in on the command line.

John Kugelman
He's only passing a single argument to the script, so this should produce: "test.sh: line 2: myscript.pl -g \"Some Example\" -n 1 -p 45: command not found".
Emil
Yeah, like I said the second works only if he removes the quotes.
John Kugelman
The eval did it for me. Ridiculously simple solution I might add... thanks.
Ed Gl
+1  A: 

Quoting is normally handled by the parser, which isn't seeing them when you substitute the value of $1 in your script.

You may have more luck with:

#!/bin/sh
eval "$1"

which gives:

$ sh test.sh 'perl -le "for (@ARGV) { print; }" "hello world" bye'  
hello world
bye

Note that simply forcing the shell to interpret the quoting with "$1" won't work because then it tries to treat the first argument (i.e., the entire command) as the name of the command to be executed. You need the pass through eval to get proper quoting and then re-parsing of the command.

This approach is (obviously?) dangerous and fraught with security risks.

Emil
A: 

if you really have to do this (for whatever reason) why not just do:

sh test.sh "'Some Example' -n 1 -p 45"

in: test.sh

RUN=myscript.pl
echo `$RUN $1

(there should be backticks ` before $RUN and after $1)

dwright
+1  A: 

I would suggest you name the perl script in a separate word, then you can quote the parameters when referring to them, and still easily extract the script name without needing the shell to split the words, which is the fundamental problem you have.

test.sh myscript.pl "-g \"Some Example\" -n 1 -p 45"

and then

#!/bin/sh
$1 "$2"
DigitalRoss