2013-08-28 86 views
4

我有這個簡單的腳本來打印出它接收,然後就退出: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 '[email protected]'; 
for p in [email protected]; 
do 
    echo "[$p]"; 
done; 
echo Using '"[email protected]"'; 
for p in "[email protected]"; 
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 [email protected] 
[This] 
[is] 
[a] 
[Test] 
[target] 
Using "[email protected]" 
[This] 
[is] 
[a] 
[Test target] 

問題:

我有一個外部的程序(我不能修改),通過這個進我的劇本,但當它執行它打印出這一點:

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

我有一種預感,它實際上是通過"This is a \"test target\""到腳本。 我怎樣才能把這個「一個參數」,並使其成爲「多個參數」,但仍然尊重組合的單詞(用引號括起來)?

回答

3

嘗試:

eval set "[email protected]" 

或(更安全,如果它可能與外殼選項開頭):

eval set -- "[email protected]" 

之後,你應該能夠使用"[email protected]"

與所有eval一樣,這具有各種各樣的危險。 :-)的危險

實施例:

$ set '`ls`' 
$ eval set -- "[email protected]" 
$ echo $# 
28 
$ echo "$1" 
COPYRIGHT 

編輯:這裏是一個protect殼功能和使用它的一個例子。我不知道我免受一切,但它得到了兩個明顯的情況:

#! /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 -- "[email protected]" 
echo "without protect, \$# is $#:" 
for arg do echo "[$arg]"; done 

set -- '-e -n $foo `ls` "bar baz"' 
eval set -- $(protect "[email protected]") 
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

+0

除了使用'eval'之外還有其他方法嗎? – justderb

+0

總有另一種方式。其他「簡單」的方式,但?沒有什麼明顯的副手。可能值得通過過濾器運行「$ @」來代替「危險」字符(至少是美元符號和反引號)。我已經寫了這個作爲一個測試,我會編輯它。 – torek

+0

'eval'會留給你四個參數,'這','是','a'和'測試目標' - 但雙引號將被刪除,因爲「test」和「target」被解釋並分組在一起。但是'eval'基本上和它一樣好。 –