对于Bash和Zsh之类的shell,我已经在Unix&Linux以及其他使用“反引号已被弃用”的网站上多次看到此评论。

这句话是对还是错?

评论

有关为什么$(...)表示法比嵌套的反引号更易于使用的示例,请参见shell脚本中为什么不反引号帮助我cd到目录。

冲压线在这里

至少有一个Unix AIX记录了反引号已过时。 “尽管ksh接受了反引号语法,但X / Open Portability Guide Issue 4和POSIX标准认为它已作废。这些标准建议可移植应用程序使用$(command)语法。” ibm.com/support/knowledgecenter/ssw_aix_71/com.ibm.aix.osdevice / ...

我在Mac 10.10上的“ GNU bash版本3.2.57(1)-发行版(x86_64-apple-darwin14)”中有明确的区别:matchingLines = $(grep -n'\ $-PARAMETER'... | .. 。)有效,matchingLines =反引号反引号相同的东西不起作用-似乎失去了反斜杠美元的反斜杠。 (这不是我的剧本...)

#1 楼

“不赞成使用”有两种不同的含义。


不赞成使用:(主要是软件功能)可以使用,但通常由于已被取代而被认为是过时且最好避免使用。 br />
—新牛津美语词典


通过此定义,不建议使用反引号。将来会被删除。

—Wikipedia


由于此定义,不建议使用反引号。 />
引用Shell命令语言的开放组规范,特别是“ 2.6.3命令替换”部分,可以看出命令替换的两种形式是:反引号(`..cmd..`)或美元括号($(..cmd..) )在规范范围内仍受支持。命令名称本身。当命令
包含以下内容时,将发生命令替换:环境(请参见Shell Execution Environment),并用命令的标准输出替换
命令替换(命令文本加上$()
反引号),并删除一个或多个序列替换末尾的字符。在输出末尾之前嵌入的字符不得删除;但是,
它们可能被视为字段定界符,并在字段拆分期间被删除,
取决于IFS的值和有效的引用。如果输出
包含任何空字节,则行为未指定。

在命令替换的反引号样式中,应保留
它的字面意思,除非后面跟有'$','\`'或<反斜杠>。匹配反引号的
搜索应由第一个未引号的
非转义反引号来满足;在此搜索过程中,如果在外壳程序注释,此处文档,嵌入式命令$(command)形式的嵌入式命令
或带引号的字符串中遇到未转义的反引号
,则未定义结果
发生。在“ `...`”序列中以单引号或双引号开头但不结束的字符串匹配的右括号组成命令。任何有效的shell
脚本都可以用于命令,除了仅由
重定向组成的脚本会产生未指定的结果。

因为大多数用例都应该使用美元括号形式而不是反引号。 (在上面的第一个意义上已弃用。)许多最著名的网站(包括U&L)也经常在整个过程中都声明这一点,因此这是合理的建议。此建议不应与一些不存在的计划从外壳中删除对反引号的支持相混淆。BashFAQ#082-为什么$(...)优于`...`(反引号)?兼容的伯恩贝壳。总是有以下几种原因
首选$(command)语法:

...

摘录


这是命令替换的较旧的Bourne兼容形式。
`...`$(...)语法均由POSIX指定,
但是尽管后者在脚本中仍然非常普遍,但后者是首选。新型命令替换已在每个现代shell(以及某些现代shell)中广泛实现。使用
反引号的唯一原因是与真实的Bourne外壳(如传家宝)兼容。
嵌套时,Backtick命令替换需要特殊的转义,而在野外发现的
示例经常被错误引用。请参阅:
为什么$(...)优于`...`(反引号)?。



POSIX标准原理

摘录


由于这些不一致的行为,对于嵌套命令替换或尝试嵌入复杂脚本的新应用程序,建议不要使用反引号的各种命令替换。 br />

注意:上面的第三段摘录继续显示了几种情况,其中反引号根本行不通,但是较新的dollar parens方法有效,从以下段落开始:


另外,反引号语法对嵌入式命令的内容有历史限制。虽然较新的“ $()”表单可以处理任何类型的有效嵌入式脚本,但带反引号的表单不能处理某些包含反引号的有效脚本。


如果您继续阅读本节,则会突出显示失败,显示使用反引号会失败的方法,但是使用较新的美元符号会起作用。
结论

因此,最好使用$ parens而不是反引号,但实际上并没有使用在技术上已“弃用”的东西,例如“这将在计划的某个时刻完全停止工作。”
读完所有这些内容后,应该强烈建议您使用美元货币,除非您特别要求与真实的原始非POSIX Bourne外壳兼容。

评论


按照大多数不赞成使用的含义,我(和您)会说反引号已被禁止使用。这主要是一个术语问题。

–StéphaneChazelas
2014年4月28日在15:54

@StephaneChazelas-同意!我将继续告诉ppl他们已被弃用,但反引号尚未正式“弃用”,因为在不久的将来它们将被主动从任何Shell的代码库中删除。至少我不知道。

–slm♦
2014年4月28日在16:00

我的解释是,仅支持反引号,因为它们在现有代码中根深蒂固,无法正式弃用。我从未听说过要在新代码中继续使用它们的争论。

–chepner
14年4月28日在16:08

@slm是的,我想您确实知道了-我被拉开了,没有注意到。几乎没有理由使用这些东西,除了在对子壳进行分层时它可以稍微清洁一点,因此$(cmd`cmd`)的混乱程度比$(cmd $(cmd))少得多-易于阅读。我只是一直认为软件中已弃用的功能已被正式标记为上游要删除的功能-我从未听说过类似的信息。我不在乎-对坟墓没有爱。

–mikeserv
2014年4月28日在18:27



您可能需要在POSIX标准基础上添加以下引号:由于这些不一致的行为,对于嵌套命令替换或尝试嵌入复杂脚本的新应用程序,建议不要使用反引号的命令替换。虽然这不是正式的弃用,因为基本原理部分是提供信息的内容,而不是规范性的内容,它的确建议应避免继续使用反引号。

– jw013
2014年4月30日在21:53



#2 楼

它不被弃用,但是反引号(`...`)是仅最老的非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\"`"


,因为$()使用全新的上下文来引用

,因为Bourne和Korn外壳将需要这些反斜杠,而Bash和dash则不需要,因此它不可移植。 br />

嵌套命令替换的语法更容易:

IPs_inna_string=`awk "/\`cat /etc/myname\`/"'{print }' /etc/hosts`


比:

x=$(grep "$(dirname "$path")" file)


因为$()强制使用一个全新的引用上下文,所以每个命令替换都受到保护并且可以处理d本身,而无需特别关注引用和转义。使用反引号时,在两个或两个以上级别后变得越来越难看。

更多示例:

x=`grep "\`dirname \"$path\"\`" file`



它解决了一个使用反引号时行为不一致的问题: >
$()输出echo '$x'




反引号语法对嵌入式命令的内容有历史限制,无法处理某些包含反引号的有效脚本,而更新的$x表单可以处理任何类型的有效嵌入式脚本。例如,这些其他有效的嵌入式脚本在左栏中无效,但在右侧有效br />
echo `echo `ls``      # INCORRECT
echo `echo \`ls\``    # CORRECT
echo $(echo $(ls))    # CORRECT



因此,echo `echo '$x'`前缀命令替换的语法应该是首选方法,因为它在外观上清晰明了(使用清晰的语法(提高了人机可读性),它是可嵌套且直观的,其内部解析是独立的,并且更加一致(以及从双引号内分析的所有其他扩展名),其中唯一的例外是反引号,并且与$x相邻时echo $(echo '$x')字符很容易被伪装,这使得阅读起来更加困难,特别是在字体较小或不寻常的情况下。来源:为什么$x优于$()(反引号)? BashFAQ上的

另请参见:


POSIX标准部分“ 2.6.3命令替换”
包含$()语法的POSIX基本原理
命令替换
bash-hackers:命令替换