1.什么是shell脚本
shell是一个命令行解释器,它的作用就是遵循一定的语法将输入的命令加以解释并传给系统。它为用户提供了一个向Linux发送请求以便运行程序的接口系统级程序,shell本身是一个用C语言编写的程序,他是用户使用Linux的桥梁。
简单来说,shell脚本就是命令的堆积。
2.shell脚本之基本格式
脚本开头:第一行,顶格写
#!/bin/bash
注释信息:shell脚本中会忽略"#"开头的行,所以为了方便自己和他人的查看,那么我们一般都会在脚本中添加注释信息方便以后观看。古人云:不添加注释的脚本都是耍流氓。通常的注释信息可以这样写:
#!/bin/bash # application # versions # date # name # email
3.shell脚本之变量
局部变量:
普通变量,仅在创建它的shell中有效
本地变量:
当前shell中的变量,本地变量包含环境变量,本地变量的非环境变量不具备继承性
环境变量:
对创建它的shell及其派生出来的子进程都有效
位置参数变量:
$1,$2,$3...
特殊变量:
$0:脚本文件路径本身
$#:脚本参数的个数
$*:所有参数(后面参数以多个字符串表示)
$@:所有参数(后面参数以一个字符串表示)
4.shell脚本之基本运算
在shell脚本基本的运算符号有:
+ - * / % **
由于shell是弱类型的编程语言,所以我们在做算术运算的时候需要这样写:
let VAR=$num1 op $num2 VAR=$[expression] VAR=$((expression)) VAR=$(expr argu1 argu2 argu3)
例:计算6+8
let VAR=6+8 VAR=$[6+8]
增强型赋值:
变量做某种算术运算后回存至此变量中
例:
自增: let VAR+=1 自减: let VAR-=1 ......
5.shell脚本之条件测试
通常情况下判断某需求是否满足,需要由测试机制来实现
可以用 "$?" 来判断上一条命令正确与否
如何编写测试表达式以实现所需的测试:
执行命令,并利用命令的状态返回值来判断:
0:成功
1-255:失败
测试表达式:
test EXPRESSION
[ EXPRESSION ]
[[ EXPRESSION ]]
那么bash的测试类型基本分为三类:
(1)数值测试:数值比较
-eq:是否等于
-ne:是否不等于
-gt:是否大于
-ge:是否大于等于
-lt:是否小于
-le:是否小于等于
例:判断2是否大于3
(2)字符串测试:字符比较
==:是否等于
> :是否大于
< :是否小于
!=:是否不等于
=~:左侧字符串是否能被右侧的PATTERN所匹配
例:判断主机名为空,或者为localhost.locadomain,或者包含localhost,或者包含linux,则通通将其设为 www.magedu.com
#!/bin/bash # H=$(hostname) [[ "$H" == " " || "$H" =~ "localhost.locadomain" || "$H" =~ "localhost" || "$H"=~"linux" ]] && hostname www.magedu.com
(3)文件测试:
存在性测试:
-a FILE
-e FILE
文件的存在性测试,存在则为真,否则则为假
存在性及类型测试:
-b FILE:是否存在为块设备文件,是则为真,否则为假
-c FILE:是否存在为字符设备文件
-d FILE:是否存在为目录文件
-f FILE:是否存在为普通文件
-h FILE或 -L FILE :是否存在为符号链接文件
-p FILE :是否存在为命令管道文件
-S FILE:是否存在为套接字文件
文件权限测试:
-r FILE :是否存在并且对当前用户可读
-w FILE :是否存在并且对当前用户可写
-x FILE :是否存在并且对当前用户可执行
特殊权限测试:
-u FILE :是否存在并且拥有SUID权限
-g FILE :是否存在并且拥有SGID权限
-k FILE :是否存在并且拥有sticky权限
文件是否有内容:
-s FILE :文件是否存在并且非空,有则为真,没有则为假
时间戳:
-N FILE:文件自从上一次读操作后是否被修改过
从属关系测试:
-O FILE :当前用户是否为文件的属主
-G FILE :当前用户是否为文件的属组
双目测试:
FILE1 -ef FILE2 :FILE1与FILE2是否指向同一个文件系统的相同inode的硬链接
FILE1 -nt FILE2 :FILE1是否新于FILE2
FILE1 -ot FILE2 :FILE1 是否旧于FILE2
例:通过命令行参数,给定两个文本文件名,如果某文件不存在,则结束脚本执行,若都存在时,返回每个文件的行数,并echo出其中行数较多的文件名
#!/bin/bash # [ $# -ne 2 ] && echo "请给定两个文本文件名" && exit 2 [ -e "$1" ] && file1=$(cat "$1" | wc -l) || exit 3 [ -e "$2" ] && file2=$(cat "$2" | wc -l) || exit 4 [ "$file1" -gt "$file2" ] && echo "$1的行数为$file1" || echo "$2的行数为$file2"
6.shell脚本之选择执行
过程式编程语言的代码执行顺序:
顺序执行:逐条执行
选择执行:
代码有一个分子:条件满足时才会执行
两个或以上的分支:只会执行其中一个满足条件的分支
循环执行:
代码片段(循环体) 要执行0、1或多个来回
shell脚本中的选择执行:
单分支的if语句:
if 测试条件;then
代码分支
fi
或者:
if 测试条件
then
代码分支
fi
双分支的if语句:
if 测试条件;then
条件为真时执行的分支
else
条件为假时执行的分支
fi
多分支的if语句:
if 测试条件;then
条件为真时执行的分支
elif 测试条件;then
elif 测试条件;then
elif 测试条件;then
......
else
条件为假时执行的分支
fi
例:
1.通过参数传递一个用户名给脚本,此用户名如果不存在的话,则进行添加
#!/bin/bash # if [ "$#" -ne 1 ];then echo "请输入一个用户名" exit 2 fi user=$(grep "^$1\>" /etc/passwd) if ! [ -s "$user" ];then useradd "$1" echo "用户$1已添加" fi
2.通过命令参数,给定两个数字,输出其中较大的数值
#!/bin/bash # if [ "$#" -ne 2 ];then echo "请给定两个数字" exit 2 fi if [ "$1" -gt "$2" ];then echo "$1" elif [ "$1" -eq "$2" ];then echo "$1=$2" else echo "$2" fi
7.shell脚本之命令交互
read [OPTIONS]...
-p'PROMPT'提示符
-t TIMEOUT
例:
1.写一个脚本,提示用户输入一个字符串,如果输入的是quit,则退出,否则,显示其输入的字符串脚本内容
#!/bin/bash # read -p "请输入一个字符串:" A if [ "$A" == quit ];then exit 2 else echo "$A" fi
2.背景:公司来了个新员工,需要给新员工开通系统帐号和统计出新员工的信息。(通过交互的方式)
让用户指定一个用户名和密码,若用户名之前存在,先进行删除。之后则为用户添加系统帐号。
完成后,需要统计员工的:手机号,email,QQ号,年龄信息,收集后存储到该用户的家目录中。
完成以上操作,询问该用户,是否需要给用户单独建立一个工作目录为/data/username,默认是需要,如果不需要,则需输入n或者N
#!/bin/bash # read -p "请输入用户名:" user grep "^$user\>" /etc/passwd > /dev/null && userdel -r $user useradd $user read -p "请输入用户密码:" pswd echo $pswd | passwd --stdin $user > /dev/null read -p "请输入手机号码:" number read -p "请输入email:" mail read -p "请输入QQ号码:" qq read -p "请输入年龄信息:" age echo "手机号码:$number,email:$mail,QQ:$qq,年龄:$age" > /home/$user/xinxi.txt read -p "是否需要建立一个工作目录[Y/N]" A if [ "$A" == Y ];then mkdir -p /date/$user echo "用户已创建,工作目录已创建" else echo $A echo "用户已创建" fi