命令替换:修订间差异

维基百科,自由的百科全书
删除的内容 添加的内容
通过翻译页面“Command substitution”创建
标签[[1]] [[1]]
 
添加更多引用细节
第1行: 第1行:
命令替换是一个实现命令交互的方法。它将一个命令的输出作为参数传给另一个命令。命令替换最初出现在 1979 年 [[Version 7 Unix|Unix 7]] 的 [[Bourne shell]]<ref>{{Cite web|title=The A-Z of Programming Languages: Bourne shell, or sh|url=https://www.arnnet.com.au/article/279011/a-z_programming_languages_bourne_shell_sh/|access-date=2023-05-07|website=www.arnnet.com.au}}</ref> 中。这之后在所有的 [[Unix shell]] 中都有它的存在。这一特性后来也被其他[[编程语言]]采用,包括 [[Perl]]、[[PHP]]、[[Ruby]]、[[PowerShell|Powershell]] 以及微软的 [[命令提示字元|CMD.exe]] 中的 FOR 和 ( ) 命令。
命令替换是一个实现命令交互的方法。它将一个命令的输出作为参数传给另一个命令。命令替换最初出现在 1979 年 [[Version 7 Unix|Unix 7]] 的 [[Bourne shell]]<ref>{{Cite web|author=Dahdah, Howard|date=2009-03-05|title=The A-Z of Programming Languages: Bourne shell, or sh, An in-depth interview with Steve Bourne, creator of the Bourne shell, or sh|url=https://www.arnnet.com.au/article/279011/a-z_programming_languages_bourne_shell_sh/|access-date=|website=Computerworld}}</ref> 中。这之后在所有的 [[Unix shell]] 中都有它的存在。这一特性后来也被其他[[编程语言]]采用,包括 [[Perl]]、[[PHP]]、[[Ruby]]、[[PowerShell|Powershell]] 以及微软的 [[命令提示字元|CMD.exe]] 中的 FOR 和 ( ) 命令。


== 语法和解析方式 ==
== 语法和解析方式 ==
第10行: 第10行:
</syntaxhighlight>存在对于语法和解析方式的不同观点和反对意见。
</syntaxhighlight>存在对于语法和解析方式的不同观点和反对意见。


尽管命令替换的语法易于输入(这对交互式命令处理器来说很重要),但由于这种语法下的左右分隔符相同<ref>{{Cite web|last=Jerry Peek|first=Tim O'Reilly & Mike Loukides|date=1998-08-04|title=UNIX Power Tools|url=http://www.c3.hu/docs/oreilly/unix/upt/ch45_31.htm|access-date=2023-05-07|website=1-56592-260-3|language=en-US}}</ref>,因此在遇到嵌套使用时很难使用。[[KornShell|Kornshell]](ksh) 借鉴了变量替换的语法风格,使用 $( ... ) 解决了这个问题。今天大多数的 Unix shell 和 [[PowerShell|Powershell]] 都支持这种语法。<syntaxhighlight lang="bash">
尽管命令替换的语法易于输入(这对交互式命令处理器来说很重要),但由于这种语法下的左右分隔符相同<ref>{{Cite web|last=Jerry Peek|first=Tim O'Reilly & Mike Loukides|date=1998-08-04|title=UNIX Power Tools|url=http://www.c3.hu/docs/oreilly/unix/upt/ch45_31.htm|access-date=2023-05-07|website=1-56592-260-3|language=}}</ref>,因此在遇到嵌套使用时很难使用。[[KornShell|Kornshell]](ksh)<ref>{{Cite book|edition=Second edition|chapter=Learning the Korn shell|url=https://www.worldcat.org/oclc/54115790|publisher=O'Reilly|date=2002|location=Sebastopol, CA|isbn=978-1-4493-7128-9|oclc=54115790|first=Arnold|last=Robbins|title=Learning the Korn Shell|year=2002|pages=127}}</ref> 借鉴了变量替换的语法风格,使用 $( ... ) 解决了这个问题。今天大多数的 Unix shell 和 [[PowerShell|Powershell]] 都支持这种语法。<syntaxhighlight lang="bash">
#!/bin/sh
#!/bin/sh
vi $(fgrep -l malloc *.c)
vi $(fgrep -l malloc *.c)
</syntaxhighlight>将输出按空格做分隔来解析的做法也遭到了批评。这种做法在早期的 [[UNIX|Unix]] 系统上表现良好,因为它的文件名中不包含空格,但在现代的 [[Microsoft Windows|Windows]] 和 [[Linux]] 系统中,由于文件名可能会包含空格,导致这样的解析方式无法正确工作。例如,在先前的两个示例中,如果通配符匹配到的文件名包含空格,该文件名将被拆分成两个单独的参数传给 shell ,这显然和预期不符。[[Hamilton C shell]] 通过双反引号符号 `` ... ``  解决了这个问题:它只在换行符处解析。
</syntaxhighlight>将输出按空格做分隔来解析的做法也遭到了批评。这种做法在早期的 [[UNIX|Unix]] 系统上表现良好,因为它的文件名中不包含空格,但在现代的 [[Microsoft Windows|Windows]] 和 [[Linux]] 系统中,由于文件名可能会包含空格<ref>{{Cite book|chapter=8|url=https://www.worldcat.org/oclc/567139717|publisher=Apress|date=2009|location=New York|isbn=978-1-4302-1998-9|oclc=567139717|first=Chris F. A.|last=Johnson|title=Pro Bash Programming: Scripting the Linux Shell|pages=84}}</ref>,导致这样的解析方式无法正确工作。例如,在先前的两个示例中,如果通配符匹配到的文件名包含空格,该文件名将被拆分成两个单独的参数传给 shell ,这显然和预期不符。[[Hamilton C shell]] 通过双反引号符号 `` ... ``  解决了这个问题:它只在换行符处解析。<ref>{{Cite web|author=Hamilton Laboratories|date=2014-12-19|title=Hamilton C shell User guide: I/O redirection: Command substitution|url=https://web.archive.org/web/20141219230358/http://www.hamiltonlabs.com/userguide/07-IORedirection.htm#CommandSubstitution|access-date=|website=web.archive.org}}</ref>


这是一个使用 PowerShell 中的 () 运算符进行命令替换的示例:<syntaxhighlight lang="powershell">
这是一个使用 PowerShell 中的 () 运算符进行命令替换的示例:<syntaxhighlight lang="powershell">

2023年5月8日 (一) 14:28的版本

命令替换是一个实现命令交互的方法。它将一个命令的输出作为参数传给另一个命令。命令替换最初出现在 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. 
  2. ^ Jerry Peek, Tim O'Reilly & Mike Loukides. UNIX Power Tools. 1-56592-260-3. 1998-08-04 [2023-05-07]. 
  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.