命令字面值¶
命令字面值是以反引號 `
或 %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