我在Unix&Linux以及其他使用“反引号已被弃用”的网站上(例如Bash和Zsh)多次见过此评论。
这句话是对还是错?
matchingLines=$( grep -n '\$-PARAMETER' ... | ... )
有效,matchingLines= backtick the same stuff backtick
不起作用-似乎在反斜杠美元中失去了反斜杠。(这不是我的剧本...)
我在Unix&Linux以及其他使用“反引号已被弃用”的网站上(例如Bash和Zsh)多次见过此评论。
这句话是对还是错?
matchingLines=$( grep -n '\$-PARAMETER' ... | ... )
有效,matchingLines= backtick the same stuff backtick
不起作用-似乎在反斜杠美元中失去了反斜杠。(这不是我的剧本...)
Answers:
“已弃用”有两种不同的含义。
不推荐使用:(主要是软件功能)可以使用,但通常已被取代,因此被认为已过时且最好避免。
—新牛津美国词典
通过此定义,不建议使用反引号。
过时的状态也可能表示该功能将来会被删除。
— 维基百科
根据此定义,不建议使用反引号。
引用壳命令语言的开放组规范,特别是“ 2.6.3命令替换”部分,可以看出,在规范的范围内,仍支持两种形式的命令替换,反引号(`..cmd..`
)或美元括号($(..cmd..)
)。
摘抄
命令替换允许替换命令名称本身来替换命令的输出。当命令包含以下内容时,应进行命令替换:
$(command) or (backquoted version): `command`
外壳程序应通过在子外壳程序环境(请参见外壳程序执行环境)中执行命令,并用命令
$()
的标准输出替换命令替换项(命令文本加上后缀或反引号)来扩展命令替换,并删除一个或多个序列替换末尾的<newline>字符。在输出末尾之前嵌入的<newline>字符不得删除;但是,根据IFS的值和有效的引用,它们可以被视为字段定界符并在字段拆分期间被消除。如果输出包含任何空字节,则行为未指定。在命令替换的加引号的样式内,<backslash>保留其字面含义,除非后面跟有'$','
\`
'或<backslash>。对匹配的反引号的搜索应由第一个未引号的非转义反引号来满足;在此搜索期间,如果在外壳程序注释,此处文档,该$(command)
格式的嵌入式命令替换或带引号的字符串中遇到了非转义的反引号,则会发生未定义的结果。在“`...`
”序列内开始但不结束的单引号或双引号字符串会产生未定义的结果。使用该
$(command)
格式,在开括号后面到匹配的闭括号后面的所有字符构成命令。可以将任何有效的Shell脚本用于命令,但仅由重定向组成的脚本会产生未指定的结果。
因为大多数用例应该使用美元括号形式而不是反引号。(在上面的第一个意义上已弃用。)许多最著名的站点(包括U&L)也经常在整个过程中都声明这一点,因此这是合理的建议。该建议不应与一些不存在的计划混淆,该计划从壳中删除了对反引号的支持。
BashFAQ#082-为什么$(...)优于`...`(反引号)?
摘抄
`...`
是仅最旧的非POSIX兼容bourne-shell所需的传统语法。始终首选$(...)
语法有几个原因:...
摘抄
这是命令替换的较早的Bourne兼容形式。无论是
`COMMANDS`
和$(COMMANDS)
语法由POSIX规定,但后者大大首选,尽管前者是可惜还是在脚本中非常普遍。新型命令替换已在每个现代Shell(以及某些现代Shell)中广泛实现。使用反引号的唯一原因是为了与真实的Bourne外壳(如传家宝)兼容。嵌套时,反引号命令替换需要特殊的转义符,并且在野外发现的示例经常被错误引用。请参见: 为什么$(...)比`...`(反引号)更受青睐?。
摘抄
由于这些不一致的行为,对于嵌套命令替换或尝试嵌入复杂脚本的新应用程序,建议不要使用反引号的命令替换。
注意:上面的第三段摘录继续显示了反引号根本不起作用的几种情况,但是较新的Dollar parens方法却起作用,从以下段落开始:
此外,反引号语法对嵌入式命令的内容有历史限制。虽然较新的“ $()”表单可以处理任何类型的有效嵌入式脚本,但带反引号的表单不能处理某些包含反引号的有效脚本。
如果您继续阅读该部分,则会突出显示失败,并显示使用反引号将失败的方式,但是使用较新的美元parens表示法则可以完成工作。
因此,最好使用美元原价而不是反引号,但实际上并没有使用在技术上已“弃用”的东西,例如“这将在计划的某个时刻完全停止工作”。
阅读完所有这些内容后,应该强烈建议您使用美元括号,除非您特别要求与真实的原始非POSIX Bourne外壳兼容。
$( cmd `cmd`)
干净之外$( cmd $(cmd))
,它的杂乱程度也要少得多-易于阅读。我只是一直认为软件中已弃用的功能已被正式标记为上游要删除的功能-我从未听说过类似的功能。我不在乎-对坟墓没有爱。
它不被弃用,但是反引号(`...`
)是仅最老的非POSIX兼容bourne-shell所要求的传统语法,并且$(...)
由于以下几个原因而被POSIX首选:
\
反引号内的反斜杠()以非显而易见的方式处理:
$ echo "`echo \\a`" "$(echo \\a)"
a \a
$ echo "`echo \\\\a`" "$(echo \\\\a)"
\a \\a
# Note that this is true for *single quotes* too!
$ foo=`echo '\\'`; bar=$(echo '\\'); echo "foo is $foo, bar is $bar"
foo is \, bar is \\
内部的嵌套引用$()
要方便得多:
echo "x is $(sed ... <<<"$y")"
代替:
echo "x is `sed ... <<<\"$y\"`"
或写类似:
IPs_inna_string=`awk "/\`cat /etc/myname\`/"'{print $1}' /etc/hosts`
因为$()
使用全新的上下文进行报价
这不是便携式的,因为Bourne和Korn外壳将需要这些反斜杠,而Bash和dash则不需要。
嵌套命令替换的语法更容易:
x=$(grep "$(dirname "$path")" file)
比:
x=`grep "\`dirname \"$path\"\`" file`
因为$()
强制使用全新的引用上下文,所以每个命令替换都受到保护,可以单独处理,而不必特别关注引用和转义。使用反引号时,两个或以上级别后变得越来越难看。
几个例子:
echo `echo `ls`` # INCORRECT
echo `echo \`ls\`` # CORRECT
echo $(echo $(ls)) # CORRECT
它解决了使用反引号时行为不一致的问题:
echo '\$x'
输出 \$x
echo `echo '\$x'`
输出 $x
echo $(echo '\$x')
输出 \$x
Backticks语法对嵌入式命令的内容有历史限制,不能处理某些包含反引号的有效脚本,而较新的$()
格式可以处理任何类型的有效嵌入式脚本。
例如,这些其他有效的嵌入式脚本在左栏中无效,但在右侧IEEE上有效:
echo ` echo $(
cat <<\eof cat <<\eof
a here-doc with ` a here-doc with )
eof eof
` )
echo ` echo $(
echo abc # a comment with ` echo abc # a comment with )
` )
echo ` echo $(
echo '`' echo ')'
` )
因此,$
-prefixed 命令替换的语法应该是首选方法,因为它在语法上清晰明了(提高了人机可读性),可嵌套且直观,内部解析是独立的,并且更加一致(与所有其他从双引号内进行解析的扩展名),其中反引号是唯一的例外,并且`
当与字符相邻时,很容易伪装字符"
,尤其是使用小字体或特殊字体时,字符甚至更难以阅读。
资料来源:为什么$(...)
比`...`
(反引号)更受青睐?在BashFAQ
也可以看看:
cd
访问目录,以获取有关为什么使用$(...)
符号比嵌套反引号更容易使用的示例。