DVK*_*DVK 149 syntax sh backticks
有两种方法可以捕获命令行的输出bash
:
Legacy Bourne shell反手``
:
var=`command`
Run Code Online (Sandbox Code Playgroud)$()
语法(据我所知,特定于Bash,或至少不受原始Bourne等非POSIX旧shell支持)
var=$(command)
Run Code Online (Sandbox Code Playgroud)与反引号相比,使用第二种语法有什么好处吗?或两者完全相同?
pax*_*blo 139
主要的是能够嵌套它们,命令中的命令,而不会失去理智,试图找出某种形式的转义是否会对反引号起作用.
一个例子,虽然有点做作:
deps=$(find /dir -name $(ls -1tr 201112[0-9][0-9]*.txt | tail -1l) -print)
Run Code Online (Sandbox Code Playgroud)
它将为您提供/dir
目录树中所有文件的列表,这些文件与2011年12月(a)中最早的日期文本文件同名.
另一个例子是获取父目录的名称(不是完整路径):
pax> cd /home/pax/xyzzy/plugh
pax> parent=$(basename $(dirname $PWD))
pax> echo $parent
xyzzy
Run Code Online (Sandbox Code Playgroud)
(a)既然特定的命令可能实际上没有用,我还没有测试过这个功能.所以,如果你投票给我,你已经忘记了意图:-)这只是为了说明如何嵌套,而不是作为一个无错误的生产就绪片段.
Jon*_*ler 56
假设您要查找与gcc
安装位置相对应的lib目录.你有一个选择:
libdir=$(dirname $(dirname $(which gcc)))/lib
libdir=`dirname \`dirname \\\`which gcc\\\`\``/lib
Run Code Online (Sandbox Code Playgroud)
第一个比第二个更容易 - 使用第一个.
ken*_*orb 31
backticks(`...`
)是最老的非POSIX兼容的bourne-shell所需的遗留语法,并且$(...)
由于以下几个原因而更为首选:
\
反引号内的反斜杠()以非显而易见的方式处理:
$ 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 \\
Run Code Online (Sandbox Code Playgroud)嵌套引用内部$()
更方便:
echo "x is $(sed ... <<<"$y")"
Run Code Online (Sandbox Code Playgroud)
代替:
echo "x is `sed ... <<<\"$y\"`"
Run Code Online (Sandbox Code Playgroud)
或写下类似的东西:
IPs_inna_string=`awk "/\`cat /etc/myname\`/"'{print $1}' /etc/hosts`
Run Code Online (Sandbox Code Playgroud)
因为$()
使用全新的上下文来引用
这是不可移植的,因为Bourne和Korn shell需要这些反斜杠,而Bash和dash则不需要.
嵌套命令替换的语法更容易:
x=$(grep "$(dirname "$path")" file)
Run Code Online (Sandbox Code Playgroud)
比:
x=`grep "\`dirname \"$path\"\`" file`
Run Code Online (Sandbox Code Playgroud)
因为$()
强制引用全新的上下文,所以每个命令替换都受到保护,可以单独处理,而不必特别关注引用和转义.当使用反引号时,它会在两级以上的级别后变得更加丑陋和丑陋.
几个例子:
echo `echo `ls`` # INCORRECT
echo `echo \`ls\`` # CORRECT
echo $(echo $(ls)) # CORRECT
Run Code Online (Sandbox Code Playgroud)它解决了使用反引用时行为不一致的问题:
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 ')'
` )
Run Code Online (Sandbox Code Playgroud)因此,$
-prefixed 命令替换的语法应该是首选方法,因为它在视觉上清晰,语法清晰(提高了人和机器的可读性),它是可嵌套和直观的,它的内部解析是独立的,并且它也更加一致(与从双引号中解析的所有其他扩展)其中反引号是唯一的例外,并且`
字符在邻近时很容易伪装"
使其更难以阅读,特别是对于小字体或不常见的字体.
来源:为什么$(...)
首选`...`
(反引号)?在BashFAQ
也可以看看:
dgw*_*dgw 22
来自man bash:
$(command)
or
`command`
Bash performs the expansion by executing command and replacing the com-
mand substitution with the standard output of the command, with any
trailing newlines deleted. Embedded newlines are not deleted, but they
may be removed during word splitting. The command substitution $(cat
file) can be replaced by the equivalent but faster $(< file).
When the old-style backquote form of substitution is used, backslash
retains its literal meaning except when followed by $, `, or \. The
first backquote not preceded by a backslash terminates the command sub-
stitution. When using the $(command) form, all characters between the
parentheses make up the command; none are treated specially.
Run Code Online (Sandbox Code Playgroud)
除了其他答案,
$(...)
Run Code Online (Sandbox Code Playgroud)
在视觉上更胜一筹
`...`
Run Code Online (Sandbox Code Playgroud)
反叛看起来太像撇号; 这取决于您使用的字体.
(而且,正如我刚才注意到的,反引号更难以输入内联代码示例.)
$()
允许嵌套.
out=$(echo today is $(date))
Run Code Online (Sandbox Code Playgroud)
我认为反引号不允许.
POSIX 标准定义了$(command)
命令替换的形式。今天使用的大多数 shell 都符合 POSIX 标准,并支持这种首选形式而不是古老的反引号符号。Shell Language 文档的命令替换部分 (2.6.3) 描述了这一点:
命令替换允许将命令的输出替换为命令名称本身。当命令被如下包围时,将发生命令替换:
$(command)
或(反引号版本):
`command`
shell 应通过 在子 shell 环境中执行命令来扩展命令替换(请参阅Shell 执行环境)并将命令替换(命令文本加上封闭的“$()”或反引号)替换为命令的标准输出,删除
<newline>
替换结束时的一个或多个字符的序列。<newline>
输出结束前的嵌入字符不得删除;但是,它们可能会被视为字段分隔符并在字段拆分期间被消除,具体取决于 IFS 的值和有效的引用。如果输出包含任何空字节,则行为未指定。在命令替换的反引号样式中,
<backslash>
应保留其字面含义,除非后跟:“$
”、“`
”或<backslash>
。匹配反引号的搜索应由第一个未加引号的非转义反引号满足;在此搜索过程中,如果在 shell 注释、here-document、$( command ) 形式的嵌入式命令替换或带引号的字符串中遇到非转义反引号,则会出现未定义的结果。在 "`...`
" 序列内开始但不结束的单引号或双引号字符串会产生未定义的结果。在 $( command ) 形式中,从左括号到匹配右括号的所有字符构成 command。任何有效的 shell 脚本都可以用于command,除了仅由重定向组成的脚本会产生未指定的结果。
命令替换的结果不应被处理以进行进一步的波浪号扩展、参数扩展、命令替换或算术扩展。如果命令替换发生在双引号内,则不应对替换结果执行字段拆分和路径名扩展。
命令替换可以嵌套。要在反引号版本中指定嵌套,应用程序应在内部反引号之前加上
<backslash>
字符;例如:
\`command\`
shell 命令语言的语法对于以“
$((
", 可以引入算术展开或以子shell开头的命令替换。算术展开有优先权;也就是说,shell首先判断是否可以将展开解析为算术展开,而只将展开解析为命令如果它确定它不能将扩展解析为算术扩展,则替换。执行此确定时,shell 不需要评估嵌套扩展。如果它遇到输入的结尾,而尚未确定它无法将扩展解析为算术扩展,则shell 应将扩展视为不完整的算术扩展并报告语法错误。符合要求的应用程序应确保将 "$(
" 和 '分开(
' 在以子shell 开头的命令替换中分成两个标记(即,用空格分隔它们)。例如,包含单个子 shell 的命令替换可以写为:
$( (command) )
这是一个遗留问题,但我想出了一个完全有效的$(...)
over示例`...`
。
我正在使用远程桌面到运行 cygwin 的 Windows 并希望迭代命令的结果。遗憾的是,由于远程桌面或 cygwin 本身,无法输入反引号字符。
假设美元符号和括号在这种奇怪的设置中更容易输入是明智的。