跳至內容

命令字面值

命令字面值是以反引號 `%x 百分比字面值分隔的字串。它會在執行時期被替換為在子 shell 中執行字串所捕獲的輸出。

相同的 跳脫字元插值規則 適用於一般字串。

與百分比字串字面值類似,%x 的有效分隔符號為圓括號 ()、方括號 []、大括號 {}、角括號 <> 和管道符號 ||。除了管道符號之外,所有分隔符號都可以巢狀使用;也就是說,字串內部的起始分隔符號會跳脫下一個結束分隔符號。

特殊變數 $? 會以 Process::Status 的形式保存命令的退出狀態。它僅在與命令字面值相同的範圍內可用。

`echo foo`  # => "foo"
$?.success? # => true

在內部,編譯器會將命令字面值重寫為對頂層方法 `() 的呼叫,並將包含命令的字串字面值作為參數:`echo #{argument}`%x(echo #{argument}) 會被重寫為 `("echo #{argument}")

安全考量

雖然命令字面值對於簡單的腳本類工具可能很有用,但在插入使用者輸入時,建議特別小心,因為它可能很容易導致命令注入。

user_input = "hello; rm -rf *"
`echo #{user_input}`

此命令將寫入 hello,然後刪除目前工作目錄中的所有檔案和資料夾。

為了避免這種情況,命令字面值通常不應與插入的使用者輸入一起使用。標準程式庫中的 Process 提供了一種安全的方式,將使用者輸入作為命令參數提供。

user_input = "hello; rm -rf *"
process = Process.new("echo", [user_input], output: Process::Redirect::Pipe)
process.output.gets_to_end # => "hello; rm -rf *"
process.wait.success?      # => true