2015-04-27 44 views
2

考慮這個的Makefile:安全地傳遞使變量shell命令

VAR1=oneword 
VAR2=two words 
VAR3=three" quoted "words 

test: 
    printf '>%s< ' "$(VAR1)" "$(VAR2)" "$(VAR3)" 
    @echo 

如果我運行它,我得到

$ make test 
printf '>%s< ' "oneword" "two words" "three" quoted "words" 
>oneword< >two words< >three< >quoted< >words< print 

,但我想獲得相同的結果,如果我跑以下命令:

$ printf '>%s< ' "oneword" "two words" "three\" quoted \"words" 
>oneword< >two words< >three" quoted "words< 

假設我不能改變的變量,也就是我的號召變爲printf莫名其妙。

換句話說:我如何將一個Make變量的內容作爲一個參數傳遞給一個shell命令,而不會分裂成幾個或任何特定的shell效果?

回答

2

製作支持export指令通過環境傳遞文字內容:

VAR1=oneword 
VAR2=two words 
VAR3=three" quoted "words 

export VAR1 
export VAR2 
export VAR3 

test: 
     printf '>%s< ' "$$VAR1" "$$VAR2" "$$VAR3" 
     echo 

輸出:

$ make test 
printf '>%s< ' "$VAR1" "$VAR2" "$VAR3" 
>oneword< >two words< >three" quoted "words< echo 
+0

謝謝,我忘了'export'。如果不介意混淆環境,這可能是一個很好的選擇。 –

+0

*點頭*。坦率地說,我更喜歡這種方法,主要是出於意識形態的原因 - 從代碼中帶外傳遞數據完全消除了任何轉義潛力 - 即使對於符合POSIX的shell,您的答案應該完全足夠。 (出於同樣的原因,我傾向於在Bobby Tables XKCD的「清理輸入」部分上留下一點皺眉,一個好的綁定參數的實現會將數據從代碼中完全帶外,從而不需要消毒)。 –

+0

......當然,「完全」假設沒有數據成爲代碼的後門,一個la Shellshock,但這是一個完全不同的討論。 –

1

我找到了解決辦法。它的可讀性並不好,但似乎非常可靠。

這個想法是在shell級別使用單引號('),因爲沒有變量插值或其他奇怪的事情發生在那裏。此外,這意味着我們需要在變量的內容擔心唯一的字符是單引號,而這些能夠可靠地取代:

VAR1=oneword 
VAR2=two words 
VAR3=three" quoted 'words 

test: 
    printf '>%s< ' '$(subst ','\\'',$(VAR1))' '$(subst ','\\'',$(VAR2))' '$(subst ','\'',$(VAR3))' 
    @echo 

現在我得到

$ make test 
printf '>%s< ' 'oneword' 'two words' 'three" quoted '\''words' 
>oneword< >two words< >three" quoted 'words< 

注如何正確逃脫',以及shell命令如何可靠地接收它。