Shell 脚本中常用的内置变量 你知道吗?

系统 Linux
在 Bash 解释器中,内置了许多变量,这些变量的功能是解释器自带的,我们在编写shell脚本时如果能灵活的使用它们,对脚本的编写效率以及差错大有帮助, 下面一一介绍这些变量。

 [[354150]]

本文转载自微信公众号「Linux开发那些事儿」,作者LinuxThings。转载本文请联系Linux开发那些事儿公众号。  

在 Bash 解释器中,内置了许多变量,这些变量的功能是解释器自带的,我们在编写shell脚本时如果能灵活的使用它们,对脚本的编写效率以及差错大有帮助, 下面一一介绍这些变量

$FUNCNAME、$LINENO、$PWD

FUNCNAME和LINENO 变量经常用于脚本的调试

FUNCNAME 表示当前函数的名字,作用范围仅限函数中使用,在函数外无值

LINENO 表示当前所在脚本中变量出现在的行号

PWD 表示当前目录, 对应于 pwd命令

现有个脚本 a.sh 内容如下

1 #!/bin/bash 
 2 
 3  
 4 testa() 
 5 { 
 6  echo 'func='$FUNCNAME,$LINENO 
 7 } 
 8  
 9  
10 testa 
11  
12 echo 'lineno:'$LINENO 
13 echo 'xx:'$FUNCNAME 
14 echo 'curpath:'$PWD 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.

执行 ./a.sh 命令, 输出如下

[tt@ecs-centos-7 ~]$ ./a.sh  
func=testa,6 
lineno:12 
xx: 
curpath:/home/tt 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

在 testa 函数中 FUNCNAME 变量值是 testa,也即函数名字,在函数外部无值

LINENO 变量无论是在函数中还是函数外,都表示当前所在的行号

$$、$PPID

这两个变量依次表示当前进程ID和父进程ID

现有 a.sh 脚本,内容如下

sleep 20 睡眠语句是为了让执行脚本进程暂缓退出,在另一个终端中验证输出的结果

#!/bin/bash 
#set -u 
 
echo 'cur pid:'$$ 
echo 'parent pid:'$PPID 
sleep 20 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

在当前终端执行 ./a.sh,结果如下

[tt@ecs-centos-7 ~]$ ./a.sh  
cur pid:13095 
parent pid:12982 
  • 1.
  • 2.
  • 3.

在执行a.sh的脚本进程退出之前,打开另一个终端,执行 ps -o pid,ppid,time,cmd -p 12982,13095 命令,结果如下

[tt@ecs-centos-7 ~]$ ps -o pid,ppid,time,cmd -p 12982,13095 
  PID  PPID     TIME CMD 
12982 12981 00:00:00 -bash 
13095 12982 00:00:00 /bin/bash ./a.sh 
  • 1.
  • 2.
  • 3.
  • 4.

从上面的结果可以看出, 执行 ./a.sh 命令之后,$$ 变量表示的是 执行a.sh脚本的进程ID 13095 ,而 12982 是它的父进程ID,也即是 PPID变量的值,它是当前bash的实例

$0,$1,$2...$n、$#

$# 表示从命令行传入脚本的参数数量

$0,$1,$2...$n 是从命令行传递到脚本的参数 $0 是脚本本身的名字 $1 是第一个参数 $2 是第二个参数,依此类推 $n 是第n个参数

第十个参数及以后的参数必须要用大括号括起来,例如: ${10}、${11}、${12} 依次表示第十个变量、第十一个变量、第十二个变量

$*、$@

都表示位置参数,不过它们之间也有些不同点

使用 $* 时,如果加上双引号,即 "$* " 的形式,那所有位置的参数会被当作一个单词来处理,如果不包含双引号,即 $* 的形式,则每个位置的参数都被当作一个独立的单词来处理

而对于 $@,无论是否加上双引号,每个位置的参数都被当作一个独立的单词来处理

现有c.sh, 内容如下

#!/bin/bash 
 
cnt=1 
echo 'test 1111' 
 
for var in "$*" 
do 
   echo "arg$cnt="$var 
   let "cnt+=1" 
done 
echo 
 
cnt=1 
echo 'test 2222' 
for var in $* 
do 
  echo "arg$cnt="$var 
  let "cnt+=1" 
done 
echo 
 
cnt=1 
echo 'test 3333' 
for var in "$@" 
do 
  echo "arg$cnt="$var 
  let "cnt+=1" 
done 
echo 
 
cnt=1 
echo "test 4444" 
for var in $@ 
do 
 echo "arg$cnt="$var 
 let "cnt+=1" 
done 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.

执行 ./c.sh 1 2 3,结果如下

[root@ecs-centos-7 ~]# ./c.sh 1 2 3 
test 1111 
arg1=1 2 3 
 
test 2222 
arg1=1 
arg2=2 
arg3=3 
 
test 3333 
arg1=1 
arg2=2 
arg3=3 
 
test 4444 
arg1=1 
arg2=2 
arg3=3 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.

从上面的结果可以看出,对于 $* 来说,加了双引号之后所有位置参数就会被视为一个单词

对于 $@ 来说,是否加双引号,结果都是一样的

所以,仅在使用双引号时,$*和 $@ 才会有差异

$?

命令、函数或者脚本的退出状态,在判断命令的执行结果或者函数的调用结果时很有用处

现有 e.sh 和 f.sh 测试脚本

e.sh 脚本

#!/bin/bash 
 
test_func() 

  if [[ $1 -eq 10 ]]; then 
        return 5 
  fi 
  return 6 

 
 
if [ $# -ge 1 ]; then 
   name="$1" 
   shift 1 
   $name "$@" 
fi 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.

f.sh 脚本

#!/bin/bash 
 
 
sh e.sh test_func 3 
echo 'exit code1:'$? 
 
sh e.sh test_func 10 
echo 'exit code2:'$? 
 
test -f $PWD/xx.txt 
echo 'exit code3:'$? 
 
test -f $PWD/e.sh 
echo 'exit code4:'$? 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.

执行 ./f.sh 命令,结果如下

[root@ecs-centos-7 ~]# ./f.sh  
exit code1:6 
exit code2:5 
exit code3:1 
exit code4:0 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

脚本 e.sh 中 test_func 函数功能是:当参数等于10时,退出状态为 5,否则为 6

sh e.sh test_func 3 命令会调用 e.sh 脚本中的 test_func函数,传入参数是 3,所以退出状态为 6,同理可知, sh e.sh test_func 10 命令的退出状态是 5

在Linux中,命令执行成功,退出状态为 0 ,失败则为非 0

test -f $PWD/xx.txt 命令是检查当前目录是否存在 xx.txt 文件,因当前目录并不存在 xx.txt,所以命令执行失败,退出状态为非 0

由于e.sh 存在于当前目录下,所以 test -f $PWD/e.sh 命令执行成功,退出状态为 0

$IFS

此变量用于 Bash 识别字符串或单词边界,默认值是空格,脚本中根据需要可以修改此变量的值

现有 b.sh脚本,内容如下

#!/bin/bash 
 
va="a:b:c" 
vb="x-y-z" 
vc="e,f,g" 
 
IFS=":" 
echo 'va:'$va 
echo 'vb:'$vb 
echo 'vc:'$vc 
 
echo 
 
IFS="-" 
echo 'va:'$va 
echo 'vb:'$vb 
echo 'vc:'$vc 
 
echo 
 
IFS="," 
echo 'va:'$va 
echo 'vb:'$vb 
echo 'vc:'$vc 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.

执行 ./b.sh 结果如下

[tt@ecs-centos-7 ~]$ ./b.sh  
va:a b c 
vb:x-y-z 
vc:e,f,g 
 
va:a:b:c 
vb:x y z 
vc:e,f,g 
 
va:a:b:c 
vb:x-y-z 
vc:e f g 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.

从结果可以看出,当 $IFS 为 : 时,字符串 "a:b:c"被解析成 a b c

当 $IFS 为 - 时,字符串 "x-y-z"被解析成 x y z

当 $IFS 为 , 时,字符串 "e,f,g"被解析成 e f g

$HOME、$USER、$UID、$GROUPS

HOME:   用户home目录 
USER:   当前用户名 
UID:    当前用户ID 
GROUPS: 当前用户组ID 
  • 1.
  • 2.
  • 3.
  • 4.
[tt@ecs-centos-7 ~]$ echo $HOME 
/home/tt 
[tt@ecs-centos-7 ~]$ echo $USER 
tt 
[tt@ecs-centos-7 ~]$ echo $UID 
1003 
[tt@ecs-centos-7 ~]$ echo $GROUPS 
1003 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.

$HOSTTYPE、$MACTYPE、$OSTYPE

这些变量都表示系统硬件

[tt@ecs-centos-7 ~]$ echo $HOSTTYPE 
x86_64 
[tt@ecs-centos-7 ~]$ echo $MACHTYPE 
x86_64-redhat-linux-gnu 
[tt@ecs-centos-7 ~]$ echo $OSTYPE 
linux-gnu 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

小结

本文介绍了一些常用的 Bash 内置变量,对于一些生僻或者平常很少用到的变量可以自行查阅相关资料

 

责任编辑:武晓燕 来源: Linux开发那些事儿
相关推荐

2024-06-12 08:05:06

2022-03-10 08:25:27

JavaScrip变量作用域

2020-10-08 18:58:46

条件变量开发线程

2024-02-19 00:00:00

Console函数链接库

2020-12-24 15:26:07

Redis数据库

2021-09-13 19:28:42

JavaNetty开发

2023-12-12 08:41:01

2018-09-07 15:23:16

2024-11-01 10:48:01

C#WPF程序

2010-03-26 15:28:05

Python编写

2021-10-14 06:52:47

算法校验码结构

2024-09-18 07:00:00

消息队列中间件消息队列

2022-09-29 15:32:58

云计算计算模式

2019-12-12 09:23:29

Hello World操作系统函数库

2024-05-28 09:12:10

2024-04-07 00:00:00

ESlint命令变量

2023-12-20 08:23:53

NIO组件非阻塞

2024-04-30 09:02:48

2023-04-26 10:21:04

2024-04-23 08:31:57

pythonfalse
点赞
收藏

51CTO技术栈公众号