什么是特殊的美元符号shell变量?

944
在Bash中,似乎有几个变量保存着特殊且一致含义的值。例如,
./myprogram &; echo $!

将返回myprogram在后台运行的进程的PID。我知道其他的方法,比如$?,我认为它是当前TTY的编号。还有其他的吗?


24
其中一些不仅限于Bash使用,它们也在其他Bourne相关的Shell中使用,并且实际上是由POSIX指定的。 - Dennis Williamson
1
关于:IFS=$'\n' 你可以参考这个链接:https://dev59.com/KG855IYBdhLWcg3w0H53 - sgu
1
@sgu 这不是一个参数,而是一种特殊的引用类型。$'\n' 是一个字面上的换行符,它是通过将双字母组\n替换为ASCII 10而得到的结果。 - chepner
3
如果您来到这里寻找 ${1}, ${*} 等,大括号只是为了消除歧义,通常是多余的。在上下文中,${x}$x 完全等价。 - tripleee
有关 $IFS 的信息,请参见 What is the exact meaning of IFS=$'\n' - Peyman Mohamadpour
$? 不是 TTY - 它是上一个执行命令的返回值。tty 是它的简单命令。 - Timo
4个回答

1643
  • $1$2$3等是位置参数
  • "$@"是一个类似数组的结构,包括所有的位置参数,如{$1, $2, $3 ...}
  • "$*"是所有位置参数的IFS扩展,即$1 $2 $3 ...
  • $#是位置参数的数量。
  • $-是当前shell设置的选项。
  • $$是当前shell的进程ID(而不是子shell)。
  • $_是最近一个参数(或在启动后立即启动当前shell的命令的绝对路径)。
  • $IFS是(输入)字段分隔符。
  • $?是最近前台管道的退出状态码。
  • $!是最近一个后台命令的进程ID。
  • $0是shell或shell脚本的名称。

大多数内容可以在Bash参考手册的特殊参数中找到。这里是shell设置的所有环境变量。此处

有关完整的索引,请参见参考手册变量索引


5
所有细节都在“bash”手册中有记录。唯一奇怪的是,“$_”仅在讨论“MAILPATH”变量中使用时提到。 - chepner
8
@chepner 在 man(1) bash 中查看 特殊参数 以获取 $_ 的其余定义。 - kojiro
10
在bash脚本中,我使用!$代替$_,因为后者有时会失败。 - user339222
3
请参考 https://unix.stackexchange.com/questions/271659/vs-last-argument-of-the-preceding-command-and-output-redirection 了解 !$$_ 的区别。 - tricasse
2
@Timo 如果命令没有在后台运行,你如何向 shell 请求 pid? - kojiro
显示剩余5条评论

53
  • $_ 是上一条命令的最后一个参数。
  • $# 是传递给当前脚本的参数数量。
  • $* / $@ 是以字符串/分隔列表的形式传递给脚本的所有参数列表。

随便想想,可以在 Google 上搜索 Bash 特殊变量。


148
我做了。他们把我送到这里来了。-- 书店小品 - greggo
1
我认为$@是字符串,而$*则是一个分隔列表(按照上述被接受答案). - RastaJedi
1
@RastaJedi:"$@"会扩展成一个列表,而"$*"则会扩展成一个单独的字符串。当"$@"在双引号内时,它具有特殊的行为。 - Keith Thompson
17
因为这个回答不够完整也不是很有用,所以被踩了。说“去谷歌一下”表现出缺乏努力,特别是考虑到绝大多数人最初是通过谷歌搜索进入这里的。我认为你至少应该添加官方文档链接。说实话,我没有将其标记为删除的原因仅仅是因为它是对问题的一个部分回答。我知道它已经有些老了,但请考虑编辑一下并提供更多细节。 - Sean the Bean

27

为了帮助理解$#$0$1、...、$n的作用,我使用以下脚本:

#!/bin/bash

for ((i=0; i<=$#; i++)); do
  echo "parameter $i --> ${!i}"
done

运行它将返回一个代表性的输出:

$ ./myparams.sh "hello" "how are you" "i am fine"
parameter 0 --> myparams.sh
parameter 1 --> hello
parameter 2 --> how are you
parameter 3 --> i am fine

8
在你的for循环中,!i是什么意思?这实际上是我在这里的原因,因为我不知道该叫它什么,所以我找不到答案。 - Anthony
10
@Anthony,这被称为变量间接引用。你可以在bash:indirect expansion, please explain?中找到其使用的良好解释。 - fedorqui

4

在处理一些示例时要注意; $0 可能包含一些前置路径以及程序名称。例如,将以下两行脚本保存为 ./mytry.sh 并执行它。

#!/bin/bash

echo "parameter 0 --> $0" ; exit 0

输出:

parameter 0 --> ./mytry.sh

这是在当前(2016年)的Bash版本中,通过Slackware 14.2实现的。

6
$0是否包含路径取决于脚本的运行方式。如果你执行了"./mytry.sh",那么$0就会显示这个。如果你输入了"/mytry.sh",你会看到完整的路径(因为shell会扩展)。如果你执行了". mytry.sh",你会看到"bash"。 - Steve Folly

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接