目录
1、shell变量不需要声明数据类型,所有的变量默认都是字符串类型
2、shell语法中为变量赋值时,等号的左右两边不允许有空格
2)系统环境变量----env命令查看环境变量 ---类似 于 C语言 中的全局变量
3、反引号--->把双引号中的命令标识出来,也就是将反引号中的内容当成一个shell命令进行解析
一、shell的初步理解
1、怎么理解shell
shell在英文中翻译为"贝壳",在贝壳内部就是linux系统内核,在贝壳外部就是用户。对于shell而
言,就是用户与内核之间的媒介。
![](https://img-blog.csdnimg.cn/9e459dff52c44492a05ad82c03c18888.png)
2、shell命令
Linux命令指的是shell命令,大多数shell命令都是存放在/bin,当我们需要使用一个命令时,实际
的流程:
![](https://img-blog.csdnimg.cn/bd6c19978fb043aebdf3c3f3f4e48b27.png)
二、shell编程
1、什么是shell编程
shell编程就是通过shell语法将shell命令组合起来,写入一个文件中。将来运行这个文件时,就会执行
里面的每一行shell语法,这个文件称之为shell脚本文件。实现更加自动化和智能化。
2、C语言编程 和 shell编程的区别
C语言程序 shell脚本程序
语法
C语言语法 shell语法
文件后缀
xxx.c xxx.sh
文件存放位置
任意目录 除了共享目录之外,一般放在家目录
是否需要编译
gcc编译 不需要编译,但是需要给权限
3、为什么要学习shell脚本编程
当前IT服务器百分之80都是linux服务器。linux服务器的日常维护和管理需要linux运维工程师,让程序
员写的代码能够高效、稳定、安全地在服务器上运行。
Linux运维工程师(OPS):
安装操作系统 Centos Ubuntu
部署代码运行环境,比如网站后台
及时修复漏洞,防止服务器被攻击,包括linux本身漏洞以及软件漏洞
监控服务器压力,别让服务器宕机。比如双十一淘宝瞬间涌入大量用户导致服务器宕机,网页无法访问或者支付宝无法使用。
分析日志,及时发现代码或者环境的问题,通知相关人员修复。
Linux运维工程师 日常管理的服务器 成千上万台,此时需要自动化管理跑一段代码就能在成千上万台服务器上完成相同的工作,比如服务器的监控。shell脚本就是实现Linux系统自动管理以及自动化运维所必备的工具,Linux 的底层以及基础应用软件的核心大都涉及 Shell 脚本的内容。每一个合格的Linux 系统管理员或运维工程师,都应该能够熟练的编写 Shell 脚本。
三、编写和运行第一个shell脚本程序
1、编写时需要注意以下几点
1)shell脚本没有main函数,没有头文件。shell脚本文件中是使用bash解析器进行解析,所以必须在
shell脚本中的第一行指明解析器的路径:
#!/bin/bash
#!是shell脚本中特殊标识符,后面必须跟着shell命令解析器的路径
2)shell脚本中没有printf函数,要输出内容到终端上,必须使用shell命令---》echo
![](https://img-blog.csdnimg.cn/cf2276d0aca6432bb6a157313b025e15.png)
2、第一个shell程序 hello.sh
#!/bin/bash
echo "hello world
3、如何运行编写好的shell程序
1)先给权限(因为默认是没有执行权限的)
chmod 777 hello.sh 或者 chmod +x hello.sh
2)执行
./hello.sh
#!/bin/bash
echo "GZ2264班 简健铭 来自广东"
echo "大家好,我是GZ2264班的吴彦祖,这是我写的第一个shell程序"
echo "作者:简健铭 职业:老六"
echo "座右铭:杀人放火金腰带"
四、变量
1、shell变量不需要声明数据类型,所有的变量默认都是字符串类型
C语言: int a;
shell: str
2、shell语法中为变量赋值时,等号的左右两边不允许有空格
C语言 int a = 10;
shell str=helloworld
3、变量的引用,需要在变量前面加入美元符号$
echo $str 或者 echo ${str}
4、变量种类
1)自定义变量 ---类似 于 C语言 中的局部变量
str=hello
2)系统环境变量----env命令查看环境变量 ---类似 于 C语言 中的全局变量
HOME: 用户主目录
PATH: 命令搜索路径
LD_LIBRARY_PATH: 动态库搜索路径
PWD: 当前路径
使用命令改变环境变量:
export PATH=$PATH:/home/china/xxx
export PATH=/home/china/xxx
5、位置变量(传递命令行参数和函数调用时传递参数)
./hello.sh aaaa bbbb
注意:
(1)在脚本中修改的环境变量只在脚本及子脚本范围内有效,要想其在外边环境中生效,则需要前面加 source
eg: source 1.sh
(2)如何使脚本(程序)后台执行
a.脚本(程序)后面加&符号,但是终端退出了,该进程也会结束
eg: ./a.out &
b.如果想让终端退出后,进程仍在:
eg: nohup ./a.out &
练习3:分别使用变量和命令行传递参数输出hello world字符串
1 变量:2 str = helloworld3 echo $str4 命令行:5 . / hello . sh helloworld6 echo $1
#!/bin/bash
#变量赋值=两边不能有空格
str=helloworld
#变量的引用 自定义变量需要定义来赋值
echo $str
#命令行传参
#./shell-变量 01 02 $0-->./shell-变量 $1-->01 $2--> 02
echo $0 $1 #类似于argv
五、shell编程符号
1、双引号 --> 作用: 把某些东西 变成 "值"
1)例如字符串中有空格,则必须使用"",如果没有空格,不加""也可以
![](https://img-blog.csdnimg.cn/8d2eac06f89a407a93bf51ad5c07d358.png)
2)在""内可以对变量进行引用
str=hello
echo "$str world"
3)在""内部是可以使用shell命令,但是使用shell命令需要使用反引号``来括住命令
#!/bin/bash
str=hello
#str="jjm"
#str="hello world"
#echo $str
echo "todao is `date`"
echo 'todao is date'
2、单引号 --->在单引号里面的内容 看做是纯粹的字符串
3、反引号--->把双引号中的命令标识出来,也就是将反引号中的内容当成一个shell命令进行解析
4、重定向符号 < << > >>
标准输入(0)/标准输出(1)/标准输错(2) 系统默认打开的文件描述符
1)输出重定向 > >>
命令的输出结果通常提交到标准输出设备(终端),但是也可以重新定个方向到其他位置,比如用一个文件来代替,这叫做输出重定向。在命令后添加>filename ,该命令(脚本)的输出就会写入到
filename这个文件中,而不是写入终端。
![](https://img-blog.csdnimg.cn/549e55ddcd87459b963c9b3fea3811d1.png)
2)输入重定向
命令的输入通常是从标准输入设备(键盘)中请求的,但是也可以重新定个方向到其他位置,比如从一个文件中请求,这叫做输入重定向。命令<filename 该命令所有的输入请求都来自filename。
比如: read str < 1. txt 从 1. txt 中读取数据,存储到变量 str 中 read 是 shell 编程中的一个函数 类似于 scanf ()
3)标准出错重定向
unix命令把大部分错误信息都写到这个设备里面。一般情况下,标准出错设备和标准输出设备是同一个设备(默认为终端)。标准出错也可以重定向到文件
命令 2 > filename命令 2 >> filename4 china @ubuntu : ~/ shelldir$ asdsds 2 > a . txt -- 把出错信息重定向到文件 a . txt 中5 china @ubuntu : ~/ shelldir$ cat a . txt6 asdsds :未找到命令
六、算术运算命令expr
expr主要是用于简单的整数计算,包括 加(+)、减(-)、乘(\*)、除(/)、取余(%)
1 #!/bin/bash2 a = 103 b = 204 val = `expr $a + $b ` ( 注意:操作数与运算符,前后至少要有一个空格 )5 echo "val: $val " ---> val : 30
1 #!/bin/bash2 a = 103 b = 204 val = `expr $a + $b \ * 4 ` ( 且不支持括号 )5 echo "val: $val " ---> val : 90
七、字符串处理
计算字符串字符个数
1 str = "hello world"2 echo "${#str}" --> 11
通配符:
1 * 代表任意长度的任意字符2 ? 代表一个长度的任意字符3 [ a-z ]: 代表一个长度的 a-z 之内的字符4 [ az ]: 代表一个长度,只能匹配 a 或者 z 的内容5 [ ^az ]: 代表一个指定范围 a/z 之外的字符 与 [az] 相反!67 %: 从右到左尽可能匹配少的字符8 %%: 从右到左尽可能匹配多的字符9 # : 从左到右尽可能匹配少的字符10 ## : 从左到右尽可能匹配多的字符
八、获取输入
read:在shell表示从终端输入
1 read val12 read - p "input data:" val1 val2 val33 read val < 1. txt // 从文本输入
注意:
1、以#开头的行,就是注释行
2、多行注释:
1 << 'COMMENT'2 ...3 COMMENT
练习4:从键盘上获取三个同学的信息,并且打印出来
#!/bin/bash
# read -p "name:" val1
# read -p "sex:" val2
# read -p "hight:" val3
# echo "***********"
# echo "name:$val1 sex:$val2 hight:$val3"
九、test语句
test语句可以测试三种对象:字符串、整数、文件属性
1、字符串测试
1 = 测试两个字符串内容是否完全一样2 != 测试两个字符串内容是否不一样3 - Z ( zero ) 测试字符串是否为空,为空,返回 true4 - n ( null ) 测试字符串是否不为空,不为空,返回 true
在测试字符串变量时,需要防止字符串为空的技巧:
引用变量后加一个额外的字符:
1 test $ { A } x = $ { B } x
2、整数测试
1 a -eq b : equal 测试两个整数是否相等2 a -ne b : not equal 测试两个是否不相等3 a -gt b : greater 测试 a 是否大于 b4 a -ge b : greater or equal 测试 a 是否大于等于 b5 a -lt b : little 测试 a 是否小于 b6 a -le b : little or equal 测试 a 是否小于等于 b
3、文件测试
1 - d name 测试 name 是否是一个目录 ( dir ) // if test -d 1.txt;then2 - f name 测试 name 是否是一个普通文件 ( file )3 - L name 测试 name 是否为符号链接文件 ( Link )4 - r name 测试 name 文件是否存在并可读 ( read )5 - w name 测试 name 文件是否存在并可写 ( write )6 - x name 测试 name 文件是否存在并可执行 ( excute )7 - s8 e 测试 name 文件是否存在并且长度不为 0 ( size )9 f1 - nt f2 测试 f1 是否比 f2 更新 ( newer than )10 f1 - ot f2 测试 f1 是否比 f2 更旧 ( older than )
test命令可以用[]来简写
1 test expression <===> [ expression ]
test的复合表达式
组合了两个或两个以上的表达式称为复合表达式,你可以用test([])内置的的操作符,也可以用条件操
作符(&& || !)来实现
1)使用test内置的操作符
test expr1 "test_buildin" expr2test_buildin :- a and- o or
2)使用条件操作符(&& || !)
test expr1 "op" test expr2
比如: test $A = '1' && test $B = '1'[ $A = '1' ] && [ $B = '1' ]
练习5: 判断一个输入的整数是否是奇数,如果是则打印yes ,否则 no
#!/bin/bash
read -p "input data:" val
if test `expr $val % 2` -eq 0;then
echo "偶数"
else
echo "奇数"
fi #与if成对存在
十、if分支语句
a.条件语句
1 第一种:2 if command ; then3 ... 语句列表4 fi5 第二种:6 if command ; then7 ... 语句列表8 else9 ... 语句列表10 fi11 第三种:12 if command ; then13 ... 语句列表14 elif command ; then15 ... 语句列表16 else17 ... 语句列表18 fi
#!/bin/bash
# read var
# if [ $var = "hello" ] ; then
# echo "yes"
# elif [ $var = "other" ] ; then
# echo "other"
# else
# echo "no"
# fi
练习6:从键盘上获取两个整数,比较大小,输出最大值
练习7:判断一个文件是否存在,若存在则打印文件的内容,不存在则输出字符串报错
练习8:用shell编写脚本程序:读取变量dir,如果该变量代表的值是目录,则切换到该目录下,
并在该目录下创建空文件file.txt,将“hello world ”写到该文件中
如果该目录不存在则创建该目录并切换过去,并显示当前绝对路径
练习7:判断一个文件是否存在,若存在则打印文件的内容,不存在则输出字符串报错
练习8:用shell编写脚本程序:读取变量dir,如果该变量代表的值是目录,则切换到该目录下,
并在该目录下创建空文件file.txt,将“hello world ”写到该文件中
如果该目录不存在则创建该目录并切换过去,并显示当前绝对路径
#!/bin/bash
#从键盘上获取两个整数,比较大小,输出最大值
# read -p "inputdata:" val1 val2
# if [ $val1 > $val2 ] ; then
# echo "max:$val1"
# else
# echo "max:$val2"
# fi
#判断一个文件是否存在,若存在则打印文件的内容,不存在则输出字符串报错
# read var
# if test -f $var ; then
# echo "is a file"
# read val<$var
# echo "file txt:$val"
# else
# echo "not a file"
# echo "`$var`"
# fi
#用shell编写脚本程序:读取变量dir,如果该变量代表的值是目录,则切换到该目录下,
# 并在该目录下创建空文件file.txt,将“hello world ”写到该文件中
# 如果该目录不存在则创建该目录并切换过去,并显示当前绝对路径
# read dir
# if test -d $dir ; then
# `cd $dir`
# `touch $dir/file.txt`
# str="hello world"
# `echo $str>$dir/file.txt`
# else
# `mkdir $dir`
# `cd $dir`
# echo "当前路径:`pwd`"
# fi
十一、多路分支语句
1、格式
1 case expression in2 pattern1 )3 ... 语句列表4 ;; // 作用类似与 C 语言的 break , 这里 ;; 不能省5 pattern2 )6 .... 语句列表7 ;;8 patternn )9 .... 语句列表10 ;;11 * ) --- 其他值12 .... 语句列表13 ;;14 esac
2、总结
1)expression 既可以是一个变量、一个数字、一个字符串,还可以是一个数学计算表达式,或者是命令的执行结果,只要能够得到 expression 的值就可以。
2)pattern 可以是一个数字、一个字符串,甚至是一个简单的正则表达式。
3)case语句真正的功能强大之处在于它可以使用模式而不是固定的字符串匹配。一个模式是由一串正规字符和特殊的通配符组成的字符串,该模式可以用正则表达式。
3、例子
例子1:
执行程序后,从键盘中获取一个值
如果该值为1,则打印one
如果该值为2,则打印two
如果该值其他值,则打印error
1 read val2 case $val in3 1 )4 echo "one"5 ;;6 2 )7 echo "two" 例子2:8 ;;9 * )10 echo "error"11 ;;12 esac
例子2:
练习8:
假设有一个文件test.txt,内容为10,要求写一个脚本,判断文件的内容 cat $1
内容是10,打印large
内容是5,打印middle
内容是1,打印small
其他值,打印other
执行脚本时 ./xxxx.sh test.txt ---> 如果参数不为1,则打印input arg error!
if [ $# != 1 ] ; then
echo "input arg error!"
fi
case `cat $1` in
10)
echo "large"
;;
5)
echo "middle"
;;
1)
echo "small"
;;
*)
echo "other" #类似于C语言里面的default
;;
esac
十二、循环语句
1、for循环
格式:
1 for 变量名 in 单词表2 do3 语句列表4 done
比如:
1 for val int 1 2 3 4 52 do3 echo $val4 done
执行结果:
1 china @ubuntu : ~/ shelldir$ chmod 777 for . sh2 china @ubuntu : ~/ shelldir$ . / for . sh3 14 25 36 47 5
1 for val int $ *2 do3 echo $val4 done
执行结果:
1 china @ubuntu : ~/ shelldir$ . / for . sh 1 2 3 4 5 62 13 24 35 46 57 6
===>for也可以写成C风格相同的for循环
for((i=1; i<=5; i++ ))
doecho " $i "done
//双圆括号(())使得shell程序中可以使用C语言的for风格
练习:写一个脚本,求1到100的和
#求1到100的和
val=0
for (( i=1; i<=100 ;i++));
do
val=`expr $i + $val`
done
echo "val:$val"
2、while循环
格式:
1 while 命令或表达式2 do3 语句列表4 done5 ===> 也可以用 C 语言的 while 风格6 while (())7 do8 语句列表9 done
比如:从键盘上获取一个最小值和最大值,打印他们两个之间的所有取值
1 read - p "min:" min2 read - p "max:" max3 while test $ min - le $ max4 do5 echo "$min"6 min = `expr $ min + 1 `7 done
练习:写一个脚本,求1到100的和
# 求1到100的和
# val=0
# i=1
# while (($i <=100))
# do
# val=`expr $val + $i`
# i=`expr $i + 1`
# done
# echo "val:$val"
3、 until
格式:
1 until 命令或表达式2 do3 done
until与while功能相似,所不同的是只有当测试的命令或表达式的值为假时,才执行循环体中的命令列表。若条件成立则退出循环。这一点与while恰好相反。
4、break 和 continue
break n
跳出
n
层循环
continue n
跳到
n
层循环语句的下一轮循环去
break
和
continue
后面不加
n,
则和
C
语言里面的含义一样
练习:写一个脚本,实现可以不断地从键盘获取数据
如果获取的数据为 "exit" ,则退出
如果获取的数据小于100,则打印值
如果获取的数据是其他的,则打印 "other"
#!/bin/bash
while read -p "请输入:" var
do
if test $var = "exit" ; then
break
elif test $var -lt 100 ; then
echo "$var"
continue
else
echo "other"
fi
done
十三、函数
格式:
1 function_name ()2 {3 ... 命令列表4 echo $ 1 $ 2 $ 35 return 1236 }
function_name:你自定义的函数名,名字的取法与C语言类似
函数的调用
function_name arg1 arg2 arg3
在函数内部 arg1==>$1 arg2==>$2 arg3==>$3
获取函数的返回值
1 function_name arg1 arg2 arg32 ret = $ ?
注意:
1、函数的返回值的大小不超过一个字节
2、SHELL没有变量作用域,如果出现重复变量名会认为是同一个。
比如:
1 get_sum ()2 {3 return `expr $ 1 + $ 2 `4 }5 read var1 ; read var26 get_sum $var1 $var27 echo $ ?
练习:编写一个脚本,封装一个函数实现比较两个数的最大值并且返回
练习:编写一个脚本,实现一个函数求a+...+b的和 a:5 b=10
# get_max()
# {
# if test $1 -gt $2 ; then
# return $1
# else
# return $2
# fi
# }
# read -p "inputdata:" var1 var2
# get_max $var1 $var2
# echo "max:$?"
get_sum()
{
sum=0
a=$1
b=$2
if test $a -ge $b ; then
while test $b -le $a
do
sum=`expr $sum + $b`
b=`expr $b + 1`
done
else
while test $a -le $b
do
sum=`expr $sum + $a`
a=`expr $a + 1`
done
fi
return $sum
}
read -p "input 2 number:" val1 val2
get_sum $val1 $val2
echo "from $val1 to $val2 sum:$?"