Linux

Shell

什么是Shell

Shell是一个命令行解释器,它接收应用程序/用户命令,然后调用操作系统内核

Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁

Shell还是一个功能相当强大的编程语言,易编写、易调试、灵活性强。

Shell 编程跟 java、php 编程一样,只要有一个能编写代码的文本编辑器和一个能解释执行的脚本解释器就可以了

入门

Linux 的 Shell 种类众多,常见的有:cat /etc/shells

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Bash由于易用和免费,Bash 在日常工作中被广泛使用。同时,Bash 也是大多数 Linux 系统默认的 Shell。

echo $SHELL

输出默认shell

脚本以#!/bin/bash 开头(指定解析器)

案例

vim helloworld.sh 在 helloworld.sh 中输入如下内容

 #!/bin/bash
 echo "helloworld" 

“#!” 是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行,即使用哪一种 Shell

脚本的常用执行方式

第一种:采用 bash 或 sh+脚本的相对路径或绝对路径(不用赋予脚本+x 权限)

(1)sh+脚本的相对路径。sh ./helloworld.sh

helloworld

(2)sh+脚本的绝对路径。 sh /home/atguigu/helloworld.sh

helloworld

(3)bash+脚本的相对路径。 bash ./helloworld.sh

helloworld

(4)bash+脚本的绝对路径。 bash /home/atguigu/helloworld.sh

helloworld

注意,一定要写成 ./test.sh ,而不是 test.sh ,运行其它二进制的程序也一样,直接写 test.sh ,linux 系统会去 PATH 里寻找有没有叫 test.sh 的,而只有 /bin, /sbin, /usr/bin,/usr/sbin 等在 PATH 里,你的当前目录通常不在 PATH里,所以写成 test.sh 是会找不到命令的,要用 ./test.sh 告诉系统说,就在当前目录找。

第二种:采用输入脚本的绝对路径或相对路径执行脚本(必须具有可执行权限+x)

(1)首先要赋予 helloworld.sh 脚本的+x 权限 chmod +x helloworld.sh

(2)执行脚本

① 相对路径。 ./helloworld.sh

helloworld

② 绝对路径。 /home/atguigu/helloworld.sh

helloworld

注意:第一种执行方法,本质是 bash 解析器帮你执行脚本,所以脚本本身不需要执行 权限。

第二种执行方法,本质是脚本需要自己执行,所以需要执行权限。

变量

语法:$变量名

$和变量名之间不能有空格。

echo $HOME 查看系统变量的值

显示当前Shell中所有的变量 env/set

自定义变量

语法

(1)定义变量:变量名=变量值,注意,=号前后不能有空格。

(2)撤销变量:unset 变量名。

(3)声明静态变量:readonly 变量,注意:不能 unset。

定义规则

(1)变量名称可以由字母、数字和下划线组成,但是不能以数字开头,环境变量名建 议大写

(2)等号两侧不能有空格。

(3)在 bash 中,变量默认类型都是字符串类型,无法直接进行数值运算。

(4)变量的值如果有空格,需要使用双引号或单引号括起来。

案例实操

1 定义变量A

A=5

echo $A

2 给A重新赋值

A=8

echo $A

3 撤销变量A

unset A

4 声明静态的变量B

readonly B=2

echo $B

设定好就修改不了

5 在bash中变量默认的类型都是字符串类型,无法直接进行数值运算

C=1+2

echo $C

6 变量的值如果有空格,需要用双引号或单引号括起来

D=“I love banzhang”

echo $D

7 可把变量提升为全局环境变量

export B

在helloworld.sh中加入 echo $B

打印输出

./helloworld.sh

特殊变量

$n

(功能描述:n 为数字,$0 代表该脚本名称,$1- 9 代表第一到第九个参数,十以上的参数需要用大括号包含,如 9 代表第一到第九个参数,十以上 的参数需要用大括号包含,如 9代表第一到第九个参数,十以上的参数需要用大括号包含,如{10}。)

案例实操

vim parameter.sh

#!/bin/bash 
echo '==========$n==========' 
echo $0 
echo $1 
echo $2 

chmod 777 parameter.sh

 ./parameter.sh cls xz 
 ==========$n========== 
./parameter
.sh
 cls

$#

(功能描述:获取所有输入参数个数,常用于循环,判断参数的个数是否正确)

在上述parameter.sh后面加入 $#

∗ * @

∗ (功能描述:这个变量代表命令行中所有的参数, * (功能描述:这个变量代表命令行中所有的参数, (功能描述:这个变量代表命令行中所有的参数,*把所有的参数看成一个整体。)

@ (功能描述:这个变量也代表命令行中所有的参数,不过 @ (功能描述:这个变量也代表命令行中所有的参数,不过 @(功能描述:这个变量也代表命令行中所有的参数,不过@把每个参数区分对待。)

在上述parameter.sh后面加入 ∗ * @

echo $* $@

∗ 和 *和 @的区别需要结合循环说明

相同点:都是引用所有参数。
不同点:只有在双引号中体现出来。假设在脚本运行时写了三个参数 1、2、3,,则 " * " 等价于 "1 2 3"(传递了一个参数),而 "@" 等价于 "1" "2" "3"(传递了三个参数)


$?

(功能描述:最后一次执行的命令的返回状态。如果这个变量的值为 0,证明上一个 命令正确执行;如果这个变量的值为非 0(具体是哪个数,由命令自己来决定),则证明 上一个命令执行不正确了。)

执行上述脚本parameter.sh

输入echo $? 判断脚本是否正确的执行

atguigu@ubuntu:~$ ./helloworld.sh
hello world
atguigu@ubuntu:~$ echo $?
0

运算符

Shell 和其他编程语言一样,支持多种运算符,包括:

  1. 算数运算符
  2. 关系运算符
  3. 布尔运算符
  4. 字符串运算符
  5. 文件测试运算符

基本语法

test condition

[ condition ](注意 condition 前后要有空格)

注意:条件非空即为 true,[ atguigu ]返回 true,[ ] 返回 false。

有两个 1是用test来进行测试 2 是用[ ]来进行测试 没有返回结果值 需要输入$? 来看结果对不对

1 算术运算符

下表列出了常用的算术运算符,假定变量 a 为 10,变量 b 为 20:

运算符说明举例
+加法expr $a + $b 结果为 30。
-减法expr $a - $b 结果为 -10。
*乘法expr $a \* $b 结果为 200。
/除法expr $b / $a 结果为 2。
%取余expr $b % $a 结果为 0。
=赋值a=$b 将把变量 b 的值赋给 a。
==相等。用于比较两个数字,相同则返回 true。[ $a == $b ] 返回 false。
!=不相等。用于比较两个数字,不相同则返回 true。[ $a != $b ] 返回 true。

注意:条件表达式要放在方括号之间,并且要有空格,例如: [ a = = a== a==b] 是错误的,必须写成 [ $a == $b ]。

乘号(*)前边必须加反斜杠()才能实现乘法运算

"$((运算式))" 或 "$[运算式]"
1)计算(2+3)* 4 的值
(1)$[]
atguigu@ubuntu:~$ S=$[(2+3)*4]
atguigu@ubuntu:~$ echo $S
(2)$(())
atguigu@ubuntu:~$ unset S
atguigu@ubuntu:~$ S=$(((2+3)*4))
atguigu@ubuntu:~$ echo $S
20

2 关系运算符

关系运算符只支持数字,不支持字符串,除非字符串的值是数字。

下表列出了常用的关系运算符,假定变量 a 为 10,变量 b 为 20:

运算符说明举例
-eq检测两个数是否相等,相等返回 true。[ $a -eq $b ] 返回 false。
-ne检测两个数是否不相等,不相等返回 true。[ $a -ne $b ] 返回 true。
-gt检测左边的数是否大于右边的,如果是,则返回 true。[ $a -gt $b ] 返回 false。
-lt检测左边的数是否小于右边的,如果是,则返回 true。[ $a -lt $b ] 返回 true。
-ge检测左边的数是否大于等于右边的,如果是,则返回 true。[ $a -ge $b ] 返回 false。
-le检测左边的数是否小于等于右边的,如果是,则返回 true。[ $a -le $b ] 返回 true。
(1)判断23 是否大于等于 22 
1  test         
 test 23 -ge 22  
 echo $? 0 
2 [ condition ]      
   [ 23 -ge 22 ] 
   echo $?
   0 

3 布尔运算符

下表列出了常用的布尔运算符,假定变量 a 为 10,变量 b 为 20:

运算符说明举例
!非运算,表达式为 true 则返回 false,否则返回 true。[ ! false ] 返回 true。
-o或运算,有一个表达式为 true 则返回 true。[ $a -lt 20 -o $b -gt 100 ] 返回 true。
-a与运算,两个表达式都为 true 才返回 true。[ $a -lt 20 -a $b -gt 100 ] 返回 false。

4 逻辑运算符

以下介绍 Shell 的逻辑运算符,假定变量 a 为 10,变量 b 为 20:

运算符说明举例
&&逻辑的 AND[[ $a -lt 100 && $b -gt 100 ]] 返回 false
||逻辑的 OR[[ $a -lt 100 || $b -gt 100 ]] 返回 true
多条件判断(&& 表示前一条命令执行成功时,才执行后一条命令,|| 表示上一条命令 执行失败后,才执行下一条命令) 
1 testcondition 
test atguigu && echo OK || echo notOK    OK 
test && echo OK || echo notOK       notOK
 2 [ condition ] 
[ atguigu ] && echo OK || echo notOK     OK 
[ ] && echo OK || echo notOK                    notOK

4 字符串运算符

下表列出了常用的字符串运算符,假定变量 a 为 “abc”,变量 b 为 “efg”:

运算符说明举例
=检测两个字符串是否相等,相等返回 true。[ $a = $b ] 返回 false。
!=检测两个字符串是否相等,不相等返回 true。[ $a != $b ] 返回 true。
-z检测字符串长度是否为0,为0返回 true。[ -z $a ] 返回 false。
-n检测字符串长度是否为0,不为0返回 true。[ -n $a ] 返回 true。
str检测字符串是否为空,不为空返回 true。[ $a ] 返回 true。

5 文件测试运算符

按照文件类型进行判断

  • -e 文件存在(existence)
  • -f 文件存在并且是一个常规的文件(file)
  • -d 文件存在并且是一个目录(directory)
3)/home/atguigu/cls.txt 目录中的文件是否存在
1  test condition
  test -e /home/atguigu/cls.txt    
 echo 
 $?
 1 
2
[ condition ] 
[ -e /home/atguigu/cls.txt ] 
echo $? 
1 

6 文件的权限

按照文件权限进行判断 -r 有读的权限(read) -w 有写的权限(write) -x 有执行的权限(execute)

helloworld.sh 是否具有写权限
1 test
 -w helloworld.sh   
 echo $?
 0
2 [ condition ]
 [ -w helloworld.sh ]
echo $?
0 

流程控制

if

if 判断

基本语法

(1)单分支 if [ 条件判断式 ];then 
程序 fi 
或者 if [ 条件判断式 ] 
then 
 fi 
(2)多分支 
if [ 条件判断式 ]
 then
 程序 
elif [ 条件判断式 ]
 then
 程序
 else 程序
 fi 

注意事项: ① [ 条件判断式 ],中括号和条件判断式之间必须有空格 ② if 后要有空格

案例实操 输入一个数字,如果是 1,则输出 banzhang zhen shuai,如果是 2,则输出 cls zhen mei, 如果是其它,什么也不输出。

vim if.sh 写入以下内容

#!/bin/bash
 if [ $1 -eq 1 ] 
then 
echo "banzhang zhen shuai" 
elif [ $1 -eq 2 ]
 then 
echo "cls zhen mei"
 fi 
chmod 777 if.sh    
 ./if.sh 1 
banzhang zhen shuai 
./if.sh 2 
cls zhen mei

case

case $变量名 in

"值 1")
 如果变量的值等于值 1,则执行程序 1 
;;
 "值 2")
 如果变量的值等于值 2,则执行程序 2 
;;
 …省略其他分支
*)
如果变量的值都不是以上的值,则执行此程序 ;; 
esac

注意事项:

(1)case 行尾必须为单词“in”,每一个模式匹配必须以右括号“)”结束。

(2)双分号“;;”表示命令序列结束,相当于 C 中的 break。

(3)最后的“)”表示默认模式,相当于 C 中的 default。

案例

输入一个数字,如果是 1,则输出 banzhang,如果是 2,则输出 cls,如果是其它,输出 renyao。 vim case.sh

#!/bin/bash
case $1 in
"1")
 echo "banzhang"
;;
"2")
 echo "cls"
;;
*)
 echo "renyao"
;;
esac

chmod 777 case.sh

./case.sh 1

./case.sh 2

./case.sh 3

**fore **

1 for ((初始值;循环控制条件;变量变化))

do 程序

done

vim for1.sh

#!/bin/bash
sum=0
for((i=0;i<=100;i++))
do
 sum=$[$sum+$i]
done
echo $sum

chmod 777 for1.sh

./for1.sh

2 for 变量 in 值 1 值 2 值 3…

do

程序

done

vim for2.sh

#!/bin/bash
#打印数字
for i in cls mly wls
do
 echo "ban zhang love $i"
done
zhuxiaoyi@zhuxiaoyi-virtual-machine:~/shell$ ./for2.sh 
ban zhang love cls
ban zhang love myl
ban zhang love wls

3 比较 ∗ 和 *和 @区别 *

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

vim for3.sh

#!/bin/bash
echo '=============$*============='
for i in $*
do
 echo "ban zhang love $i"
done
echo '=============$@============='
for j in $@
do 
 echo "ban zhang love $j"
done

zhuxiaoyi@zhuxiaoyi-virtual-machine:~/shell$ ./for3.sh 1 2 3
=========$*========
ban zhang love 1
ban zhang love 2
ban zhang love 3
========$@=========
ban zhang love 1
ban zhang love 2
ban zhang love 3

*2 当它们被双引号“”包含时,$会将所有的参数作为一个整体,以“$1 2 … 2 … 2n”的形 式输出所有参数;$@会将各个参数分开,以“$1” “ 2 ” … “ 2”…“ 2”n”的形式输出所有参数

vim for4.sh

#!/bin/bash
echo '=============$*============='
for i in "$*"
#$*中的所有参数看成是一个整体,所以这个 for 循环只会循环一次
do
 echo "ban zhang love $i"
done
echo '=============$@============='
for j in "$@"
#$@中的每个参数都看成是独立的,所以“$@”中有几个参数,就会循环几次
do
 echo "ban zhang love $j"
done

zhuxiaoyi@zhuxiaoyi-virtual-machine:~/shell$ ./for4.sh cls mly wls
==========$*==========
ban zhang love cls mly wls
========$@===========
ban zhang love cls
ban zhang love mly
ban zhang love wls

while

基本语法

while
 [ 条件判断式 ] 
do 程序
 done

案例实操

vim while.sh

#!/bin/bash
sum=0
i=1
while [ $i -le 100 ]
do
 sum=$[$sum+$i]
 i=$[$i+1]
done
echo $sum

退出循环

跳出循环

在循环过程中,有时候需要在未达到循环结束条件时强制跳出循环,Shell使用两个命令来实现该功能:break和continue。

break命令

break命令允许跳出所有循环(终止执行后面的所有循环)。

下面的例子中,脚本进入死循环直至用户输入数字大于5。要跳出这个循环,返回到shell提示符下,需要使用break命令。

#!/bin/bash
while :
do
    echo -n "输入 1 到 5 之间的数字:"
    read aNum
    case $aNum in
        1|2|3|4|5) echo "你输入的数字为 $aNum!"
        ;;
        *) echo "你输入的数字不是 1 到 5 之间的! 游戏结束"
            break
        ;;
    esac
done

执行以上代码,输出结果为:

输入 1 到 5 之间的数字:3
你输入的数字为 3!
输入 1 到 5 之间的数字:7
你输入的数字不是 1 到 5 之间的! 游戏结束

continue

co