Shell编程
1.Shell是什么
shell是一个命令行解释器,它为用户提供了一个向Linux内核发送请求以便运行程序的界面系统级程序,用户可以用Shell来启动,挂起,停止甚至是编写一些程序
2.Shell脚本的执行方式
-
脚本格式要求:
- 脚本以
#!/bin/bash
开头 - 脚本需要有可执行权限
- 脚本以
-
编写第一个Shell脚本
需要说明:创建一个Shell脚本,输出hello world! viM hello.sh #!/bin/bash echo "hello world!"
3.Shell脚本常用执行方式
-
方式1:输入脚本的绝对或相对路径
说明:首先要赋予hello.sh脚本的+x权限,再执行脚本
比如:./hello.sh 或者使用绝对路径 /root/shcode/hello.sh
-
方式2:sh+脚本
说明:不用赋予脚本+x权限,直接执行即可
比如:
sh hello.sh
,也可以使用绝对路径
-
[root@localhost shcode]# ll
total 4
-rw-r--r--. 1 root root 32 Jan 1 17:50 hello.sh
[root@localhost shcode]# chmod a+x hello.sh
[root@localhost shcode]# ls
hello.sh
[root@localhost shcode]# ll
total 4
-rwxr-xr-x. 1 root root 32 Jan 1 17:50 hello.sh
[root@localhost shcode]# ./hello.sh
hello world!
[root@localhost shcode]# /root/shcode/hello.sh
hello world!
[root@localhost shcode]# chmod a-x hello.sh
[root@localhost shcode]# ll
total 4
-rw-r--r--. 1 root root 32 Jan 1 17:50 hello.sh
[root@localhost shcode]# sh hello.sh
hello world!
[root@localhost shcode]#
2.Shell的变量
Shell变量介绍
- Linux shell中的变量分为:系统变量和用户自定义变量
- 系统变量:
$HOME $PWD $SHELL $USER
等待。查询某个系统变量的语法:如:echo $HEMO
- 显示当前所有Shell的变量语法:
set
Shell变量的定义
基本语法:
- 定义变量:变量名=值
- 撤销变量:unset 变量名
- 声明静态变量:
readonly
变量,注意:不能unset
定义变量的规则:
- 变量名称可以由字母,数字和下划线组成,但是不能以数字开头。如5S=100(是错误的)
- 等号两侧不能有空格
- 变量名称一般习惯为大写,这是一个规范,我们需要遵守即可
将命令的返回值赋给变量
-
A=`date` 反引号,运行是里面的命令,并把结果返回给变量A A=$(date)等价于反引号
案例
1.定义变量A
2.定义撤销变量A
3.声明静态的变量是B=2,不能unset
#!/bin/bash
#一般定义变量时都大写,注意是:等号左右两边不能有空格
#1.定义变量A
A=100
echo "A=$A" //定义变量A的值为100,并输出(双引号,弱引用)
echo A=$A //这句与上面的语句作用一样
#2.定义撤销变量A
unset A //撤销变量A
echo A=$A //输出的值是:A=
#3.声明静态的变量是B=2,不能unset
readonly B=2
echo "B=$B"
#unset B //注意静态变量不能撤销变量,否则报错
#单引号,强引用
echo 'My A is $ A' //这是强引用,直接输出单引号中的内容
#反引用,命令引用
echo `date`
echo $(date) //这两句作用一样
total 8
-rw-r--r--. 1 root root 32 Jan 1 17:50 hello.sh
-rwxr--r--. 1 root root 634 Jan 1 18:53 var.sh
[root@localhost shcode]# ./var.sh
A=100 //定义变量A的值为100,并输出(双引号,弱引用)
A=100 //这句与上面的语句作用一样
./var.sh: line 9: unset: `//撤销变量A': not a valid identifier
A= //输出的值是:A=
B=2
My A is $ A //这是强引用,直接输出单引号中的内容
Sat Jan 1 18:54:43 PST 2022
Sat Jan 1 18:54:43 PST 2022 //这两句作用一样
[root@localhost shcode]# vim var.sh
3.设置环境变量(全局变量)
基本语法
export
变量名=变量值 (功能描述:将shell变量输出为环境(全局变量))source
配置文件(功能描述:让修改后的配置信息立即生产)echo $变量名
(功能描述:查询环境变量的值)
案例
在/etc/proflie文件中定义TOMCAT_HOME环境变量(全局变量)
查看环境变量TOMCAT_HOME的值
在另外一个shell程序中使用TOMCAT_HOME
注意:在输出TOMCAT_HOME环境变量(全局变量)前,需要让其生效
source /etc/profile
shell脚本的多行注释:
:<<!
内容
!
位置数变量
介绍:作用就是实现动态传入参数
当我们执行一个shell脚本时,如果希望获取到命令行的参数信息,就可以使用到位置参数变量
比如:./myshell.sh 100 200
这个就是一个执行shell命令行,可以在myshell脚本中获取到参数信息
基本语法:
$n (功能描述:n为数字,$0代表命令本身就是文件名,$1-$9代表第一到第九个参数,十个以上的参数需要用大括号包含,如${10})
$*(功能描述:这个变量代表命令行中所有的参数,$*把所有的参数看成一个整体)
$@(功能描述:这个变量代表命令行中所有的参数,不过$@把每个参数区对待)
$#(功能描述:这个变量代表命令行中所有参数的个数)
位置参数变量
案例:编写一个shell脚本myshell.sh,在脚本中获取到命令行的各个参数信息
[root@localhost shcode]# vim myshell.sh
[root@localhost shcode]# sh myshell.sh 100 200
文件名=myshell.sh
第一个参数值=100,第二参数值=200
所有参数个数=2
所有参数=100 200
所有参数=100 200
[root@localhost shcode]# vim myshell.sh
#!/bin/bash
echo "文件名=$0"
echo "第一个参数值=$1,第二参数值=$2"
echo "所有参数个数=$#"
echo "所有参数=$*"
echo "所有参数=$@"
~
预定义变量
基本介绍:
就是shell设计者事先已经定义好的变量,可以直接在shell脚本中使用
基本语法:
$$(功能描述:当前进程号PID)
$!(功能描述:后台运行的最后一个进程的进程号PID)
$?(功能描述:最后一次执行命令的返回状态,如果返回0,说明命令正确执行,返回非0,说明执行失败)
案例:
在一个shell脚本中简单使用一下预定义变量preVar.sh
echo "当前执行的进程号ID=$$" //返回是当前执行preVar.sh的进程号
#以后台方式执行preVar.sh脚本,并返回进程ID 号
/root/shcode/myshell.sh &
echo "执行的结果是:$?"
~
[root@localhost shcode]# sh preVar.sh
当前执行的进程号ID=5257 //返回是当前执行preVar.sh的进程号
后台执行的进程ID号=5258
执行的结果是:0
preVar.sh: line 4: /root/shcode/myshell.sh: Permission denied
[root@localhost shcode]#
运算符
基本介绍:
学习在shell中进行各种运算操作
基本语法:
$((运算式))
或$[运算式]
或者EXPR m + n
//expression表达式- 注意expr运算符间要有空格,如果希望将expr的结果赋给某个变量,使用反引号``
expr m - n
expr \* , / ,% 乘 除 取余
- 注意是:expr中的乘法要加反斜杠
案例:
1.计算:(2+3)*4
2.请求出命令行的两个参数【整数】的和
#!/bin/bash
#1.计算:(2+3)*4
RESULT1=$(((2+3)*4))
echo RESULT1=$RESULT1
#方式二:
RESULT2=$[(2+3)*4]
echo RESULT2=$RESULT2
#方式三:
TEMP=`expr 2 + 3`
#注意是运算符中间要有空格
RESULT3=`expr $TEMP \* 4`
#注意expr运算中乘号需要加反斜杠
echo "TEMP=$TEMP"
echo "RESULT3=$RESULT3"
#请求出命令行的两个参数【整数】的和
RESULT4=$[($1+$2)]
echo "RESULT4=$RESULT4"
条件判断
判断语句:
基本语法:
[ condition ] //注意condition前后必须要有空格
非空返回true,可以使用$?验证(0为true,>1为false,意思就是[]中的内容不为空就返回true)
案例:
[ hspEdu ] //true
[] //返回false
[ condition ] && echo OK || echo notok //条件满足,执行后面的语句
常用判断条件参数
字符串比较 | 描述 |
---|---|
= | 字符串1等于字符串2,返回真 |
== | 字符串1等于字符串2,返回真 |
!= | 字符串1不等于字符串2 |
-n “字符串” | 长度不为0,则真 |
-z “字符串” | 长度为0,则真 |
两个整数的比较 | |
-lt | 小于 |
-le | 小于等于 |
-eq | 等于 |
-gt | 大于 |
-ge | 大于等于 |
-ne | 不等于 |
按照文件权限进行判断 | |
-r | 有读的权限 |
-w | 有写的权限 |
-x | 有执行的权限 |
按照文件类型进行判断 | |
-f | 文件存在且为普通文件,则真 |
-e | 文件存在(目录或普通文件),则真 |
-d | 文件存在且为目录,则真 |
f1 -nt f2 | 文件f1 比f2 新(修改时间),则真 |
f1 -ot f2 | 文件f1 比f2 旧(修改时间),则真 |
案例:
1."ok"是否等于"ok"
判断语句使用:=
2.23是否大于等于22
判断语句使用:-ge
3.判断 /root/shcode/eeje.txt目录中的文件是否存在
判断语句: -f
#!/bin/bash
#1."ok"是否等于"ok"
#判断语句使用:=
if [ "ok" = "ok" ]
then
echo "成功"
fi
#2.23是否大于等于22
#判断语句使用:-ge
if [ 23 -ge 22 ]
then
echo "为真"
fi
#3.判断 /root/shcode/eeje.txt目录中的文件是否存在
#判断语句: -f
if [ -f /root/shcode/eeje.txt ]
then
echo "存在"
else
echo "不存在"
fi
~
流程控制
if
单分支
基本语法
第一种方式:
if 条件测试表达式; then
操作语句(可以多条)
fi
第二种方式:
if 条件测试表达式
then
操作语句(可以多条)
fi
if
双分支语句
if 条件测试表达式; then
操作语句1 (可以多条)
else
操作语句2 (可以多条)
fi
if
多分支语句
if 条件测试表达式; then
操作语句1 (可以多条)
elif 条件测试表达式; then
操作语句2 (可以多条)
else
操作语句3 (可以多条)
fi
注意事项:[ 条件判断式 ] ,中括号和条件判断式之间必须有空格
应用实例:ifCase.sh
实例:请编写一个Shell程序,如果输入的参数,大于等于60,输出及格了,如果小于60,则输出不及格
#!/bin/bash
#实例:请编写一个Shell程序,如果输入的参数,大于等于60,输出及格了,如果小于60,则输出不及格
if [ $1 -gt 60 ];then
echo "及格了,不用挂科了"
else
echo "不及格了,挂科了重修吧,垃圾"
fi
#方式二
if [ $1 -gt 60 ];then
echo "不错"
elif [ $1 -lt 60 ];then
echo "挂科了"
fi
~
case语句
语法:
case $变量名 in
值1)
操作语句1(可以多条)
;;
值2)
操作语句2(可以多条)
;;
......
值N)
操作语句N(可以多条)
;;
*)
操作语句N+1(可以多条)
esac
case
语句的变量值与值1,值2,值N进行逐一比较,直到找到匹配的值,执行后遇到;;
跳出
注意:值1,值2,值N必须是常量或正则表达式
案例:
编写Shell脚本判断用户从键盘中输入的是一个字符 是否为字母,数字,其他符号
#!/bin/bash
#编写Shell脚本判断用户从键盘中输入的是一个字符 是否为字母,数字,其他符号
CASE=$1
case $CASE in
[a-zA=Z])
echo "为一个字母"
;;
[0-9])
echo "为一个数字"
;;
*)
echo "为其他符号"
esac
~
for
循环语句
基本语法1:
for 变量 in {list}(或值1,值2,。。。值N)
do
操作语句(可以多条)
done
此for循环执行次数和list列表中常数或字符串的个数相同,先将in后list列表的第一个常数或字符串赋值给变量,然后执行循环体;接着list列表第二个赋值给变量,再次执行循环体。这个过程持续到list列表执行完毕,然后执行done后操作命令
案例
1.打印命令行输入的参数{这里可以看出$* 和 $@区别}
#!/bin/bash
#打印命令行输入的参数「这里可以看出$* 和 $@的区别」
#注意 $* 是把输入的参数,当做一个整体,所以只会输出一句
for i in "$*"
do
echo "num is $i"
done
echo "++++++++++++++++++++++++++++++++++++++++++++++"
#使用$@来获取输入的参数,注意这里分别对待,所以有个参数输出几行
for j in "$@"
do
echo "num is $j"
done
2.显示5次欢迎操作
#!/bin/bash
for i in 1 2 3 4 5 6
do
echo "welocme,$i times"
done
for语法2:
for((表达式1;表达式2;表达式3))
do
操作语句(可以多条)
done
案例:
1.求1到100的和
2.求1~N的奇数和
#!/bin/bash
#1.求1到100的和
sum=0
for((i=1;i<=100;i++))
do
sum=$[ $sum + $i ]
done
echo "sum的和sum=$sum"
echo "====================================="
#2.求1~N的奇数和
sun=0
for((j=1;j<$1;j=j+2))
do
sun=$[ $sun + $j ]
done
echo "sun的和sun=$sun"
while循环
语法:
while 条件测试表达式
do
操作语句(可以多条)
done
案例:
1.从命令行输入一个数N,统计从1+。。。+N的值是大小
#!/bin/bash
#1.从命令行输入一个数N,统计从1+。。。+N的值是大小
sum=0
i=0
while [[ $i -le $1 ]]
do
sum=$[sum+i ]
i=$[i+1]
done
echo "sum的和sum=$sum"
echo "++++++++++++++++++++++++++++++++++++++++"
sun=0
j=0
while [ $i -le $1 ]
do
sun=$[$sun+$j]
j=$[$j+1]
done
echo "sun的和sun=$sun"
read
读取控制台输入
基本语法:
read(选项)(参数)
选项:
-p:
-t:指定读取值时等待时间(秒),如果没有在指定的时间内输入,就再等待了
参数:变量:指定读取值的变量名
案例:
1.读取控制台输入一个NUM1值
2.读取控制台输入一个NUM2值,在10秒内输入
#/bin/bash
#1.读取控制台输入一个NUM1值
read -p "请输入一个值NUM1=" NUM1
echo "NUM1的值为NUM1=$NUM1"
#2.读取控制台输入一个NUM2值,在10秒内输入
read -t 10 -p "请输入一个值NUM2=" NUM2
echo "NUM2=$NUM2"
函数
说明是basename
函数就是返回文件的名字
说明是dirname
返回文件的路径,不包括名字
自定义函数
基本语法:
function 函数名 ()
{
Action(动作);//代码
return int;//返回值
}
调用直接写函数名:函数名 值(传入的值)
案例:
计算输入两个参数的和(动态获取)
#!/bin/bash
#计算输入两个参数的和(动态获取)
function getSum ()
{
sum=$n1+$n2;
echo "$sum";
}
read -p "请输入n1=" n1
read -p "请输入n2=" n2
getSum $n1 $n2