命令替换是一个实现命令交互的方法。它将一个命令的输出作为参数传给另一个命令。命令替换最初出现在 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。

另见

参考资料

Wikiwand in your browser!

Seamless Wikipedia browsing. On steroids.

Every time you click a link to Wikipedia, Wiktionary or Wikiquote in your browser's search results, it will show the modern Wikiwand interface.

Wikiwand extension is a five stars, simple, with minimum permission required to keep your browsing private, safe and transparent.