9 shell
bash脚本编程:
脚本文件格式:
第一行,顶格:#!/bin/bash
注释信息:#
代码注释:
缩进,适度添加空白行;
语言:编程语法格式,库,算法和数据结构
编程思想:
问题空间 --> 解空间
变量:
局部变量:
本地变量:
环境变量:
位置参数变量:
特殊变量:
数据类型:字符型、数值型、
弱类型:都默认为处理为字符型
算数运算:
+,-,*,/,%,**
let VAR=$num1 op(运算符) $num2
var=$[exoresslon]
var=$((expression))
var=$(expr argu1 argu2 argu3)
注意:有些时候乘法符号(*)需要转义
增强型赋值:
变量做某种算数运算后回存至此变量中
let i=$i+=#
let i+=#
+=,-=,*=,/=,%=,...
自增运算:
let VAR=$[$VAR+1]
let VAR+=1
let VAR++
自减运算:
let VAR=$[$VAR1]
let VAR-=1
let VAR--1
练习:
1、写一个脚本
计算/etc/passwd文件中的第10个用户和第20个用户的id号之和
id1=$(head -10 /etc/passwd | tail -1 | cut -d: -f3)
id2=$(head -20 /etc/passwd | tail -1 } cut -d: -f3)
2、写一个脚本
计算/etc/rc.d/init.d/functions和/etc/inittab文件的空白行数之和
grep "^[[:space:]]*$" /etc/rc.d/init.d/ | wc -l
条件测试:
判断某需求是否满足,需要由测试机制来实现;
如何编写测试表达式以实现所需的测试
(1)执行命令,并利用命令状态返回值来判断
0:成功
1-255:失败
(2)测试表达式
test EXPRESSION
[ EXPRESSION ]:注意:EXPRESSION前后两端必须有空格,否则为语法错误
[[ EXPRESSION ]]:注意:EXPRESSION前后两端必须有空格,否则为语法错误
bash的测试类型:
数值测试
字符串测试
文件测试
数值测试:数值比较
-eq:是否等于:[$num1 -eq $num2]
-ne:是否不等于;
-gt:是否大于,表示左侧是否大于右侧
-ge:是否大于等于
-lt:是否小于
-le:是否小于等于
字符串测试:
==:是否等于
>:是否大于
<:是否小于
|=:是否不等于
=~:左侧字符串是否能够被右侧的PATTERN(模式)所匹配
-z “STRING”:判断指定的字串是否为空,空则为真,不空则假
-n “STRING”:判断指定的字符串是否不空,不空则真,空则为假
注意:
(1)字符串要加引号
(2)要使用双中括号[[ ]]
文件测试:
存在性测试:
-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
组合测试条件:
逻辑运算:
第一种方式:
COMMAND1 && COMMAND2
COMMAND1 || COMMAND2
! COMMAND
第二种方式:
[[ EXPRESSION1 -a EXPRESSION2 ]]
[[ EXPRESSION1 -o EXPRESSION2 ]]
[[ ! EXPRESSION1
练习:将当前主机名称保存至hostNAME变量中:
主机名如果为空,或者为localhost.localdomain,则将其设置为www.magedu.com
脚本的状态返回值:
默认是脚本中执行的最后一条命令的状态返回值;
自定义状态退出状态码:
exit [n]:n为自己指定的状态码
注意:shell进程遇到exit时,即会终止,因此,整个脚本执行即为结束
向脚本传递参数:
位置参数变量
ls /etc /var
myscript.sh argu1 argu2
引用方式:
$1,$2,...${10},${11},...
轮替:
shift [n]:位置参数轮替
练习:写一个脚本,通过命令传递两个文本文件路径给脚本,计算其空白行之和
#!/bin/bash
#
file1=$(grep "^$" $1 | wc -l)
file2=$(grep "^$" $2 | wc -l)
sum=$[$file1+$file2]
echo ${sum}
特殊变量:
$0:脚本文件路径本身
$#:脚本参数的个数
$*:所有参数;(将所有每个参数当成独立的字符串)
$@:所有参数;(将所有参数当成一个字符串)
过程式编程语言的代码执行顺序:
顺序执行:逐条运行
选择执行:
代码有一个分支:条件满足时才会执行
两个或以上的分支:只会执行其中一个满足其中一个满足条件的分支
循环执行:
代码片段(循环体)要执行0、1或多个来回
选择执行:
单分支if语句:
if 测试条件;then
代码分支
fi
双分支的if语句:
if 测试条件;then
条件为真时执行的分支
else
条件为假时执行的分支
fi
示例:通过参数传递一个用户名给脚本,此用户不存在时则添加之
#!/bin/bash
#
if ! grep "^$1\>" /etc/passwd &> /dev/null; then
useradd $1
echo $1 | passwd --stdin $1 &> /dev/null
echo "Add user $1 finished"
fi
#!/bin/bash
#
if [ $# -lt 1 ]; then
echo "At least one username"
exit 2
fi
if ! grep "^$1\>" /etc/passwd &> /dev/null; then
useradd $1
echo $1 | passwd --stdin $1 &> /dev/null
echo "Add user $1 finished"
fi
#!/bin/bash
#
if [ $# -lt 1 ]; then
echo "At least one username"
exit 2
fi
if grep "^$1\>" /etc/passwd &> /dev/null; then
echo "user $1 exists"
else
useradd $1
echo $1 | passwd --stdin $1 &> /dev/null
echo "Add user $1 finished"
fi
练习1:通过命令行参数给定两个数字,输出其中较大的数值
#!/bin/bash
#
if [ $# -lt 2 ];then
echo "Two integers"
exit 2
fi
if [ $1 -ge $2 ]; then
echo "Max number:$1"
else
echo "Max number:$2"
fi
#!/bin/bash
#
declare -i max
if [ $# -lt 2 ];then
echo "Two integers"
exit 2
fi
if [ $1 -ge $2 ]; then
max=$1
else
max=$2
fi
echo "max number:${max}"
#!/bin/bash
#
if [ $# -lt 2 ];then
echo "Two integers"
exit 2
fi
declare -i max=$1
if [ $1 -lt $2 ]; then
max=$2
fi
echo "max number:${max}"
练习2:通过命令行参数给定一个用户名,判断其ID号是偶数还是奇数
1 #!/bin/bash
2 #
3 if [ $# -lt 1 ];then
4 echo "Please input a argument"
5 exit 1
6
7 fi
8 idnum=$(id -u $1)
9 let mod=${idnum%2}
10 if [ $mod -eq 0 ];then
11 echo "$1 is even"
12 else
13 echo "$1 is odd"
14 fi
练习3:通过命令行参数给定两个文件名,如果某文件不存在,则结束脚本执行
都存在时返回每个文件的行数,并说明其中数较多的文件
#!/bin/bash
#
if [ $# -lt 2 ];then
echo "请给定两个参数"
exit 2
fi
if [ -e $1 -a -e $2 ];then
totalLines=$[ $(grep ".*" $1 | wc -l)+$(grep ".*" $2 | wc -l) ]
echo "The total lines are $totalLines"
else
echo "The file doesn't exists !"
exit 1
fi
#!/bin/bash
#
if [ $# -lt 2 ];then
echo "请给定两个参数"
exit 2
fi
if [ -e $1 -a -e $2 ];then
totalLines=$[ $(cat $1 | wc -l)+$(cat $2 | wc -l) ]
echo "The total lines are $totalLines"
else
echo "The file doesn't exists !"
exit 1
fi