Shell 三三两两

Posted gageshen

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Shell 三三两两相关的知识,希望对你有一定的参考价值。

在Shell脚本中或多或少遇到$1-$9 , $0 , $? , $! , $$ , $*, $# , $@ 这些特殊意义的命令符。如果你是一位初学者,那么恭喜你看它就像看老道写的符箓,有点摸不着边?是要死记硬背?还是理解一下再记忆呢?我想还是理解一下再记吧!

简要说明一下:

一、与参数相关: $1-$9 , $0 ,$# ,  $*, $@

1)$1-$9   表给Shell的第几个参数:

  在计算机语言编写一段代码总会涉及到什么形参、实参,即一段代码需要传递参数来保持灵活性。那么我们在编写shell脚本时,实际上就是实现一段功能的脚本代码,为了应对脚本灵活性那么就需要参数,那么参数们在shell脚本中使用时总要一个编号吧,否则怎么知道你是第一个,他是第二个……。现在shell爸爸说了,$1就表示第一个参数,$2就表示第2个参数,以此类推到$9表示第9个参数了;那么还要给shell脚本第10个,第11个……怎么办?shell爸爸说前面我有点考虑不足,$10到底表示第一参数$1值再加个0呢?还是第10个参数?所以shell规定了,要表示第10个,第11个……用$包围起来,$10表示第10个参数,$11表示第11个参数,……以此类推。

2) $0 表示执行本Shell的脚本/命令的名称。

  前面$1-$9表示给shell脚本的第几个参数,那么谁需要这些参数呢?这不简单,还有谁要啊?不就是我们编写的shell脚本需要参数嘛!那么$0就是表示这位需要参数的shell脚本奶爸。也正因为这shell奶爸需要参数,所以也就在$0这奶爸的带领下有了$1,$2……$9一群参数。下面编写一个shell脚本说明一下$0和$1-$9:

 

 1 [root@ecs-jumperserver ~]# mkdir /shell
 2 [root@ecs-jumperserver ~]# cd  /shell
 3 [root@ecs-jumperserver shell]#vim myPapaShell.sh
 4 #!/bin/bash
 5 
 6 echo "IamPapa:$0"
 7 echo "IamParameter1: $1"
 8 echo "IamParameter2: $2"
 9 echo "IamParameter3: $3"
10 
11 [root@ecs-jumperserver shell]#chmod +x myPapaShell.sh
12 [root@ecs-jumperserver shell]#./myPapaShell.sh firstPara  secondPara thirdPara
13 IamPapa: ./myPapaShell.sh
14 IamParameter1: firstPara
15 IamParameter2: secondPara
16 IamParameter3: thirdPara

 

 3)$# 表示传给shell脚本的参数个数,即传了几个参数给shell脚本(#符号看上去有点像算盘)。

现在shell脚本奶爸不好当啊,有些时候它能量大一下子聚了好多参数,有时候能量不足,只聚了两三只小猫。shell脚本老爸这下犯愁了,谁知道给我传了多少个参数。这时$#手拿大算盘噼里啪啦就给shell脚本老爸知道现在有多少个参数。

4)$* 和$@ 表示所有参数列表

当看到*符号时,就想到所有。特别在匹配中表示任意字符就全部概念;而看到@就想到微信、QQ中@all,而shell脚本中又能@谁?@只能是参数。$* 和$@ 都是列举出所有传给shell脚本奶爸的参数。但是$* 和$@还是存在区别,区别如下:

$* 和 $@ 都表示传递给函数或脚本所有参数不被双引号(" “)包含时,都以"$1"  "$2"……"$n"的形式输出所有参数。

但是当$* 和 $@被双引号(" “)包含时不同了"$*" 会将所有的参数作为一个整体,以"$1 $2 …$n"的形式输出所有参数;而"$@" 则会将各个参数分开,以"$1" "$2"……"$n"的形式输出所有参数。$@就像微信和QQ中@一样,不仅支持@all还能@各分开的参数。

 下面列举一个shell脚本说明$# ,$* ,$@

 

[root@ecs-jumperserver shell]# cd /shell
[root@ecs-jumperserver shell]# vim myParaShell.sh 
#!/bin/bash

echo "Count the Parameter: $#"

echo ######       $*      ########
for i in $* ;do
let j++
echo "Parameter$j: $i"
done

j=0
echo ######       $@      ########
for i in $@ ;do
let j++
echo "Parameter$j: $i"
done

j=0
echo ######       "$*"    ########
for i in "$*" ;do
let j++
echo "Parameter$j: $i"
done

j=0
echo ######      "$@"      ######
for i in "$@" ;do
let j++
echo "Parameter$j: $i"
done

[root@ecs-jumperserver shell]# chmod +x myParaShell.sh 
[root@ecs-jumperserver shell]# ./myParaShell.sh first
Count the Parameter: 1
######       $*      ########
Parameter1: first
######       $@      ########
Parameter1: first
######       "$*"    ########
Parameter1: first
######      "$@"      ######
Parameter1: first
[root@ecs-jumperserver shell]# ./myParaShell.sh first second
Count the Parameter: 2
######       $*      ########
Parameter1: first
Parameter2: second
######       $@      ########
Parameter1: first
Parameter2: second
######       "$*"    ########
Parameter1: first second
######      "$@"      ######
Parameter1: first
Parameter2: second

 

二、与进程号PID相关 $$ , $!

1) $$ 表示shell脚本运行的当前进程PID号。

2) $! 表示shell脚本最后运行的后台进程的PID(通过jobs查看的后台进程),即后台运行的最后一个进程的进程PID号。

  :$! 仅仅针对在运行本shell脚本中的后台进程的PID记录,它是一个局部变量的概念。通俗讲如果shell脚本中含有$!,那么它只记录当前shell脚本运行期间开启的最后一个后台进程PID。shell脚本之后台进程变化它一律不管,相互隔离。($1-$9 , $0 , $? , $! , $$ , $*, $# , $@ 都是局部变量个概念,都是只记录当前shell脚本运行期间内容值。)

  :即使现在jobs中已经没有后台进程了,如执行完毕等,$!还会保留最后一个(最新一次加入的)后台运行进程的PID号,直到有最新的后台进程加入时才会更新$!。

 

 1 [root@ecs-jumperserver shell]# vim myProcShell.sh 
 2 #!/bin/bash
 3 
 4 echo "the shell script PID: $$"
 5 
 6 sleep 600 &
 7 sleep 60 &
 8 echo "the last job PID: $!"
 9 [root@ecs-jumperserver shell]# chmod +x myProcShell.sh 
10 [root@ecs-jumperserver shell]# ./myProcShell.sh 
11 the shell script PID: 5861
12 the last job PID: 5863
13 [root@ecs-jumperserver shell]# 
14 [root@ecs-jumperserver shell]# cp myProcShell.sh myProcShell1.sh 
15 [root@ecs-jumperserver shell]# vim myProcShell1.sh
16 #!/bin/bash
17 
18 echo "the shell script PID: $$"
19 
20 echo "the last job PID: $!"
21 [root@ecs-jumperserver shell]# chmod +x myProcShell1.sh
22 [root@ecs-jumperserver shell]# sleep 600 &
23 [1] 5893
24 [root@ecs-jumperserver shell]# ./myProcShell1.sh
25 the shell script PID: 5894
26 the last job PID:                       #$!仅针对运行的本shell的后台进程PID记录。
27 [root@ecs-jumperserver shell]# 

 

 三、结束代码   $?

1) $?  表示最后运行的命令的结束代码(返回值),即执行上一个指令的返回值(显示最后命令的退出状态)

 其中指令的返回值:

    0    :表示正常,没有错误。

    其他值(非0) :表示是有错误,具体是什么错误查看该指令的帮助。  

 

[root@ecs-jumperserver shell]# vim myCommandShell.sh 
#!/bin/bash

echo "last command status: $?"

num=2
[ $num -lt 3 ]
echo "$num < 3:$?"
[ $num -gt 3 ]
echo "$num > 3:$?"
[root@ecs-jumperserver shell]# chmod +x myCommandShell.sh 
[root@ecs-jumperserver shell]# x=2
[root@ecs-jumperserver shell]# [ $x -lt 0 ]
[root@ecs-jumperserver shell]# ./myCommandShell.sh 
last command status: 0
2 < 3:0
2 > 3:1
[root@ecs-jumperserver shell]# [ $x -lt 0 ]
[root@ecs-jumperserver shell]# echo $?
1
[root@ecs-jumperserver shell]#

 

小结:

  $1-$9 , $0 , $? , $! , $$ , $*, $# , $@ 都是局部变量概念,只记录当前shell脚本运行期间的内容。在这些内容中可以把分层三类:与参数相关的,与进程相关的 和 与指令结束代码相关的。

 

参考:

https://blog.csdn.net/baidu_28126759/article/details/87863361

https://blog.csdn.net/xgt_520/article/details/78738320

https://www.runoob.com/linux/linux-shell-passing-arguments.html

以上是关于Shell 三三两两的主要内容,如果未能解决你的问题,请参考以下文章

怎样制作LINUX启动U盘 ?

子shell

什么是Linux的登录shell与非登录shell?

Shell基本概述

交互式shell和非交互式shell,登录shell和非登录shell的区别

shell批量执行多个shell脚本