Bash脚本传递一个参数,但我想要多个

时间:2013-08-28 17:54:37

标签: bash

我有这个简单的脚本来打印它收到的内容然后退出:

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

如果我执行:./echoparams This is a "test target"它将打印出来:

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]

问题:

我有一个外部程序(我无法修改)将其传递到我的脚本中,但是当它执行时会打印出来:

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"]

我有一种预感,它实际上是将"This is a \"test target\""传递给脚本。 如何使用此“一个参数”并将其设为“多个参数”,但仍然尊重组合词(带有引号)?

1 个答案:

答案 0 :(得分:3)

尝试:

eval set "$@"

或(如果它可能以shell选项开头,则更安全):

eval set -- "$@"

之后,您应该可以使用"$@"

与所有eval一样,这有各种各样的危险。 : - )

危险的例子:

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

编辑:这是一个protect shell函数和一个使用它的例子。我不确定我是否能够抵御一切,但它有两个明显的例子:

#! /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

当我运行它时:

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]

如果其他字符需要引用,很明显如何将它们添加到protect