命令替換是一個實現命令交互的方法。它將一個命令的輸出作為參數傳給另一個命令。命令替換最初出現在 1979 年 Unix 7Bourne shell[1] 中。這之後的所有 Unix shell 中都有它的存在。這一特性後來也被其他程式語言採用,包括 PerlPHPRubyPowershell 以及微軟的 CMD.exe 中的 FOR 和 ( ) 命令。

語法和解析方式

編輯

Shell 通常用創建一個子進程的方式實現命令替換。該子進程運行第一個命令,並將它的標準輸出通過管道返回給 shell ,shell 會讀取得到的輸出並以空格作為分隔來解析。在管道關閉或者子進程終止前,shell 會一直等待,因為它無法確定子進程是否完成了全部的輸出。因此,shell 會等待第一個子進程運行結束,然後才創建第二個子進程並運行下一個命令。

這個 C shell 示例演示了如何利用 fgrep 搜索包含 malloc 的所有 C 文件,並使用 vi 對搜索到的文件進行編輯。這裏的 ` ... ` 是原始風格的語法,即使用反引號作為分隔符。這一風格被所有常見的Unix shell支持。

#!/bin/csh
vi `fgrep -l malloc *.c`

存在對於語法和解析方式的不同觀點和反對意見。 儘管命令替換的語法易於輸入(這對交互式命令處理器來說很重要),但由於這種語法下的左右分隔符相同[2],因此在遇到嵌套使用時很難使用。Kornshell(ksh)[3] 借鑑了變量替換的語法風格,使用 $( ... ) 解決了這個問題。今天大多數的 Unix shell 和 Powershell 都支持這種語法。

#!/bin/sh
vi $(fgrep -l malloc *.c)

將輸出按空格做分隔來解析的做法也遭到了批評。這種做法在早期的 Unix 系統上表現良好,因為它的文件名中不包含空格,但在現代的 WindowsLinux 系統中,由於文件名可能會包含空格[4],導致這樣的解析方式無法正確工作。例如,在先前的兩個示例中,如果通配符匹配到的文件名包含空格,該文件名將被拆分成兩個單獨的參數傳給 shell ,這顯然和預期不符。Hamilton C shell 通過雙反引號符號 `` ... ``  解決了這個問題:它只在換行符處解析。[5] 這是一個使用 PowerShell 中的 () 運算符進行命令替換的示例:

$MyVariable = (ls)
echo $MyVariable

表達式替換

編輯

在相關的程式語言 Common Lisp 和 Scheme 中,可以使用反引號(或稱為「准引號」)運算符標記的表達式來調用功能。類似地,在 ABC 程式語言中,可以在文本顯示(字符串字面量)中使用反引號括起來的表達式。例如,ABC 語言中的命令 WRITE '2 + 2 = 2+2' 的輸出結果為 2 + 2 = 4。

另見

編輯

參考資料

編輯
  1. ^ Dahdah, Howard. The A-Z of Programming Languages: Bourne shell, or sh, An in-depth interview with Steve Bourne, creator of the Bourne shell, or sh. Computerworld. 2009-03-05. (原始內容存檔於2023-05-13). 
  2. ^ Jerry Peek, Tim O'Reilly & Mike Loukides. UNIX Power Tools. 1-56592-260-3. 1998-08-04 [2023-05-07]. (原始內容存檔於2023-05-12). 
  3. ^ Robbins, Arnold. Learning the Korn shell. Learning the Korn Shell Second edition. Sebastopol, CA: O'Reilly. 2002: 127. ISBN 978-1-4493-7128-9. OCLC 54115790. 
  4. ^ Johnson, Chris F. A. 8. Pro Bash Programming: Scripting the Linux Shell. New York: Apress. 2009: 84. ISBN 978-1-4302-1998-9. OCLC 567139717. 
  5. ^ Hamilton Laboratories. Hamilton C shell User guide: I/O redirection: Command substitution. web.archive.org. 2014-12-19. (原始內容存檔於2014-12-19).