Bash script passed one parameter, but I want several

I have this simple script to print what it receives, and then just exit:

IFS="|${IFS}"; echo "$# parameters"; echo Using '$*'; for p in $*; do echo "[$p]"; done; echo Using '"$*"'; for p in "$*"; do echo "[$p]"; done; echo Using ' $@ '; for p in $@ ; do echo "[$p]"; done; echo Using '" $@ "'; for p in " $@ "; do echo "[$p]"; done 

If I ./echoparams This is a "test target" : ./echoparams This is a "test target" It will print:

 4 parameters Using $* [This] [is] [a] [Test] [target] Using "$*" [This|is|a|Test target] Using $@ [This] [is] [a] [Test] [target] Using " $@ " [This] [is] [a] [Test target] 

Problem:

I have an external program (which I cannot change) that passes it to my script, but when it runs it, it outputs the following:

 1 parameters Using $* [This] [is] [a] ["test] [target"] Using "$*" [This is a "test target"] Using $@ [This] [is] [a] ["test] [target"] Using " $@ " [This is a "test target"] 

I have a suspicion that it actually passes "This is a \"test target\"" to the script. How can I take this “one parameter” and make it “several parameters”, but still observing the combined words (with quotes surrounding it)?

+4
source share
1 answer

Try:

 eval set " $@ " 

or (safer if it can start with shell options):

 eval set -- " $@ " 

After that you will be able to use " $@ " .

As with all eval s, this one has all sorts of dangers. :-)

Hazard example:

 $ set '`ls`' $ eval set -- " $@ " $ echo $# 28 $ echo "$1" COPYRIGHT 

Edit: here is a protect shell function and an example of its use. I'm not sure I'm defending myself from everything, but he gets two obvious cases:

 #! /usr/bin/env bash protect() { local quoted quoted="${1//$/\\\$}" quoted="${quoted//\`/\\\`}" # use printf instead of echo in case $1 is (eg) -n printf %s "$quoted" } foo=expanded set -- '-e -n $foo `ls` "bar baz"' eval set -- " $@ " echo "without protect, \$# is $#:" for arg do echo "[$arg]"; done set -- '-e -n $foo `ls` "bar baz"' eval set -- $(protect " $@ ") echo "with protect, \$# is $#" for arg do echo "[$arg]"; done 

When I ran it:

 without protect, $# is 46: [-e] [-n] [expanded] [OUT] [a.py] [ast_ex.py] ---snipped remaining ls output for space reasons--- [bar baz] with protect, $# is 5 [-e] [-n] [$foo] [`ls`] [bar baz] 

If other characters require quotation marks, obviously how to add them to protect .

+3
source

Source: https://habr.com/ru/post/1499458/


All Articles