2012-04-11 25 views
0

我有一個Bash腳本調用另一個Bash腳本。被調用的腳本會做一些修改並檢查一些事情,轉移,然後傳遞調用者的命令行的其餘部分。帶雙引號的參數列表在Bash中沒有正確通過

在被調用的腳本中,我已經驗證了我已經管理好所有的東西並準備好調用。這裏的一些調試的代碼風格,我已經把在:現在

echo $SVN $command [email protected] > /tmp/shimcmd 
bash /tmp/shimcmd 
$SVN $command [email protected] 

,在/ tmp/shimcmd你會看到:

svn commit --username=myuser --password=mypass --non-interactive --trust-server-cert -m "Auto Update autocommit Wed Apr 11 17:33:37 CDT 2012" 

也就是說,內置命令,所有在一行,非常好,包括-m「我的帶空格的字符串」部分。

這是完美的。它的「bash/tmp/shimcmd」執行效果也很好。

但我當然不希望這個愚蠢的tmp文件等(只用它來調試)。問題是,直接調用命令,通過代替墊片文件:

$SVN $command [email protected] 

導致svn命令本身不帶空格接收引號的字符串 - 它garbles的「-m‘我的字符串用空格’ '參數並且將命令作爲'm我的字符串與空格'一樣傳遞。

我已經嘗試了所有瘋狂的逃生方法無濟於事。簡直不敢相信它在困擾着我。同樣,通過將相同的東西($ SVN $ command $ @)回顯到一個文件中,然後執行該文件,它就是FINE。但是直接調用了引用的字符串。這一元素單獨束縛。

任何想法?

+0

你能發佈一些具體步驟來獲得這種行爲?我在重現問題時遇到了問題。 – jimw 2012-04-11 23:18:53

+0

@jimw這是一個非常常見的反模式 - 基本上,你不能指望字符串分裂做正確的事情;他應該使用數組來代替。 – 2012-04-11 23:23:07

+0

非常真實。通常我可以通過擺弄弄清楚這些引用問題,但如果我們談論的是良好的編程習慣,那麼你是完全正確的。我必須承認,當我在我的bash腳本中需要數組時,我通常會轉而使用perl或python。 – jimw 2012-04-11 23:26:25

回答

0

你嘗試:

eval "$SVN $command [email protected]" 

+0

Presto!只需添加「eval」:eval「$ SVN $ command $ @」就可以實現。工作恰到好處!非常感謝所有的想法 - 現在只用簡單的評估來完成git-er-done。 – Danimo 2012-04-11 23:46:52

+1

@ user1327769請不要這樣做。如果處理不可信的輸入,使用eval嚴重不安全,而使用數組安全地處理這些情況。請參閱http://mywiki.wooledge.org/BashFAQ/048 – 2012-04-12 00:02:51

+0

上述工作在任何符合POSIX的shell中。這個問題的基本思想是,運行存儲在各個變量中的命令。如果你不相信這個命令的內容,那麼這個方法是錯誤的。例如。如果有人可以操縱'$ SVN',這樣就可以實現'rm -rf /'(而且你是root用戶),那麼避免使用eval不會對你有所幫助。 – Kaz 2012-04-12 00:13:24

0

下面就來說明問題的方式:

$ args='-m "foo bar"' 
$ printf '<%s> ' $args 
<-m> <"foo> <bar"> 

而這裏的,以避免它的方式:

$ args=(-m "foo bar") 
$ printf '<%s> ' "${args[@]}" 
<-m> <foo bar> 

在後一種情況下,參數表是一個數組,而不是一個引用的字符串。

請注意,順便說一下,它必須是"[email protected]",而不是[email protected],以獲得此行爲(避免字符串拆分,以有利於尊重數組條目的邊界)。

0

echo -n -e $SVN \"$command\" > /tmp/shimcmd 
for x in "[email protected]" 
    do 
    a=$a" "\"$x\" 
    done 
echo -e " " $a >> /tmp/shimcmd 
bash /tmp/shimcmd 

或者乾脆

$SVN "$command" "[email protected]" 
+0

如果你想安全地逃避一個字符串,'printf%q'是規範的方式,而不是像這樣寫一大堆意大利麪條。 – 2012-04-12 00:03:50

+0

當然,對於「規範」的值不等於「便攜」或「POSIX標準」。這可能是一種方便的方式,也可能是一種GNU-y方式,但規範是某種加載的詞。 – Kaz 2012-04-12 00:18:40

相關問題