$ echo $(date)
Thu Jul 2 16:33:11 SGT 2015
$ echo ${date}
$ name=foo
$ echo $(name)
ksh: name: not found
$ echo ${name}
foo
好像${variable}
和 一样$variable
,而$()
是执行命令。为什么要用${}
then?
答案1
$(command)
是“命令替换”。正如你所理解的,它运行command
,捕获其输出,并将其插入到包含$(…)
;例如,
$ ls -ld $(date +%B).txt
-rwxr-xr-x 1 Noob Noob 867 Jul 2 11:09 July.txt
${parameter}
是“参数替换”。在 shell 的 man 页面中可以找到很多信息,重击(1), 在下面 ”参数扩展”标题:
${parameter}
的价值范围被替换。以下情况需要使用括号范围是具有多于一位数字的位置参数,或者当范围后面跟着一个不应被解释为其名称一部分的字符。
有关位置参数,请参阅“位置参数”,如下。在最常见的用法中,如其他答案所示,
parameter
是变量名。${…}
如上段末尾所述,该形式允许您获取变量的值(即),并在其后紧跟字母、数字或下划线:$variable_name
$ 动物=猫 $ 回显 $animals # 没有这样的变量“动物”。 $ echo ${animal}s 猫 $ 回显 $animal_food # 没有这样的变量“动物食物”。 $ 回显 ${animal}_food 猫食
您也可以使用引号来执行此操作:
$ echo "$animal"s 猫
或者,作为选项练习,您可以使用第二个变量:
$ 复数=s $ echo $animal$plural 猫
但这只是第一步。手册页中的下一段很有趣,尽管有点神秘:
如果第一个字符范围
是一个感叹号(!
),引入了一层变量间接寻址。Bash 使用由其余变量组成的变量的值范围
作为变量的名称;然后扩展此变量,并在其余的替换中使用该值,而不是范围本身。这被称为间接扩张。
…(例外)... 感叹号必须紧跟在左括号后面,以引入间接引用。
除了举例之外,我不知道如何才能更清楚地说明这一点:
$ 动物=猫 $ echo $animal 猫 $ cat=tabby $ 回显 $cat 虎斑猫 $ 回显 ${!animal} 虎斑猫 # 如果$动物是“猫”, 然后${!动物}是$猫, IE,“虎斑猫”
所以我们将其称为步骤 1½。步骤 2 中您可以做很多有趣的事情:
$ 动物=猫 $ echo ${#animal} 3 # 字符串长度 $ echo ${animal/at/ow} 奶牛 # 代换
{
如果没有牙套,你就无法做任何事}
。
位置参数
考虑一下人造的例子:
$ cat myecho.sh 回显 $1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 $14 $15 $ ./myecho.sh 嘿,diddle diddle,猫和小提琴,牛跳过了月亮。 嘿,骗子骗子,猫和小提琴,Hey0 Hey1 Hey2 Hey3 Hey4 Hey5
因为 shell 无法理解$10
,$11
等。它将$10
其视为${1}0
。但它确实理解${10}
、${11}
等,正如手册页中提到的那样(“具有多位数字的位置参数”)。
但实际上不要这样编写脚本;有更好的方法来处理长参数列表。
上述内容(以及更多形式的构造)在 shell 的手册页中有更详细的讨论,${parameter…something_else}
重击(1)。
关于引文的说明
请注意,除非有充分理由不这样做,否则你应该始终引用 shell 变量,并且你当然你知道自己在做什么。相比之下,虽然括号很重要,但它们并不像引号那么重要。
$ filename="童谣.txt" $ ls -ld ${文件名} ls:无法访问 Nursery:没有此文件或目录 ls:无法访问 rhyme.txt:没有此文件或目录 $ ls -ld "$文件名" -rwxr-xr-x 1 Noob Noob 5309 7月 2 11:09 童谣.txt
这也适用于位置参数(即命令行参数;例如"$1"
)以及命令替换:
$ ls -ld $(date "+%B %Y").txt ls:无法访问 July:没有此文件或目录 ls:无法访问 2015.txt:没有此文件或目录 $ ls -ld "$(日期 "+%B %Y").txt" -rwxr-xr-x 1 Noob Noob 687 2015 年 7 月 2 日 11:09.txt
看Bash 命令替换时不转义引号$(
了解有关引文与…… 之间相互作用的简要论述)
。
答案2
在您的示例中,$var 和 ${var} 相同。但是,当您希望在字符串中扩展变量时,花括号很有用:
$ string=foo
$ echo ${string}bar
foobar
$ echo $stringbar
$
因此,花括号提供了一种替换变量的方法,以便获得要替换的新变量的名称。
答案3
我通常在字符串中更常见到这种情况。类似下面的代码不会起作用:
var="a"
echo "$varRAW_STRING"
但这将:
var="a"
echo "${var}RAW_STRING"
正如您正确指出的那样,$()
用于执行命令:
dir_contents=$(ls)
你也可以使用反引号,但我发现它$()
更通用。首先,反引号不能(轻易)嵌套。
date_directory=`ls `date '+%Y-%m-%d'`` # Makes no sense
date_directory=$(ls $(date '+%Y-%m-%d')) # Much better