2016-08-04 45 views
2

在Scala中如何完成類似diff <(echo aoeu) <(echo snth)如何在Scala中執行Bash過程替換?

我使用the sys.process interface如下嘗試:

"diff <(echo aoeu) <(echo snth)".! 

......然而,這並不能解釋爲<()替代子。

+1

' 「富」!'使用'/斌/ sh',沒有慶典,作爲外殼解釋'foo'爲腳本。即使您的'/ bin/sh'由bash提供,當以這種方式調用時,它將以POSIX兼容模式運行。 –

回答

3
import scala.sys.process._ 

def diff(one: String, two: String): 
    String = Seq(
    "bash", "-c", """ 
     diff <(printf '%s\n' "$1") \ 
      <(printf '%s\n' "$2"); retval=$? 
     ((retval == 1)) || exit "$retval" 
    """, "_", one, two).!! 

這可以在實踐中得到檢驗:

scala> diff("hello", "world") 
res1: String = 
"1c1 
< hello 
--- 
> world 
" 

打破了這種推理:

  • 調用的順序,而不是字符串,允許數據(在我實例helloworld;在你的,aoeusnth)傳遞出來的帶外來自代碼。當這些內容被參數化時,這對於避免injection attacks至關重要。
  • 調用bash爲您的可執行確保process substitution的語法。
  • 檢查的1退出狀態(和它強迫爲0)避免階治療其中diff返回指示該兩個輸入是不相同的作爲錯誤退出狀態的情況下,同時確保其他錯誤仍然成爲階例外。
  • 使用printf '%s\n' "$1"而不是echo "$1"避免了the POSIX definition of echo(具體參見APPLICATION USAGE部分)中的含糊性。
  • 傳遞的_一個顯式的參數填充所述argv[0]插槽,(又名$0)。

注意,調用序列,而不是一個字符串,也可以防止您從在很多情況下都需要殼Seq("hello", "world").!不需要調用任何外殼,但可以實現爲直接啓動名爲hello的可執行文件,而"hello world".!相當於Seq("sh", "-c", "hello world").!,與兼顧性能和成本實現所需潛在的安全漏洞額外的可執行文件調用。請參閱Shellshock以獲取(現在接近普遍修補的)情況的示例,其中沒有明確的用戶控制參數的shell調用在實踐中可能仍然存在漏洞(當從遵循CGI約定的Web服務器調用以將請求參數作爲環境導出時變量);在可行的情況下避免不必要的外殼是優選的行爲