bash脚本编程:整数测试及特殊变量
exit:退出脚本
exit #
如果脚本没有明确定义退出状态码,那么,最后执行的一条命令的退出码即为脚本的退出状态码。
bash中常用的条件测试有三种:
测试方法:
命令测试法 [ expression ]
关键字测试法 [[ expression ]]
test expression
整数测试:
-gt,-le,-ne,-eq,-ge,-lt
INT1=63
INT2=77
[ $INT1 -eq $INT2 ]
[[ $INT1 -eq $INT2 ]]
test $INT1 -eq $INT2
文件测试:
-e FILE 路径:测试文件是否存在
-f FILE 路径:测试文件是否为普通文件
-d FILE 路径:测试指定路径是否为目录
-r FILE:测试当前用户对指定文件是否有读权限;
-w:是否有写权限
-x:是否有执行权限
\[ -e /etc/inittab ]
多分支的if语句:
if 判断条件1; then
statement1
...
elif 判断条件2; then
statement2
...
else
statement4
...
fi
测试脚本是否有语法错误:
bash -n 脚本名称
bash -x 脚本:单步执行
练习:写一个脚本
给定一个文件:
如果是一个普通文件,就显示之
如果是一个目录,亦显示之
否则,此为无法识别文件
#!/bin/bash
FILE=/etc/rc.d/rc.sysinit
if [ ! -e $FILE ]; then
echo "No such file"
exit 6
fi
if [ -f $FILE ];then
echo "Common file."
elif [ -d $FILE ];then
echo "Directory"
else
echo "Unkown"
fi
练习:写一脚本
能接受一个参数(文件路径)
判定:此参数如果是一个存在的文件,就显示“OK”
$1表示脚本第一个参数
#!/bin/bash
if [ $# -lt 1 ]; then
echo "Usage: ./filetest3.sh ARG1 [ARG2...] "
exit
fi
if [ -e $1 ];then
echo "OK"
else
echo "No such file."
fi
位置变量:
$1,$2,…
shift 轮换/轮替
#!/bin/bash
echo $1
shift 2
echo $1
shift 2
echo $1
练习:写一个脚本
给脚本传递两个参数(整数):
显示此两者之和,之积
#!/bin/bash
if [ $# -lt 2 ];then
echo "Usage:cacl.sh ARG1 ARG2"
exit 8
fi
echo "The sum is: $[$1+$2]."
echo "The prod is: $[$1*$2]"
特殊变量:
$?
$# 参数的个数
$* 参数列表
$@ 参数列表
sed命令(stream Editor):
流编辑器
基本用法:
行编辑器(全屏编辑器:vi)
模式空间
默认不编辑源文件,仅对模式空间中的数据做处理;而后,处理结束后,将模式空间打印
sed 'AddressCommand' file ...
-n:静默模式,不再默认显示模式空间中的内容
-i:直接修改原文件
-e SCRIPT -e SCRIPT:可以同时执行多个脚本
-f /PATH/TO/SED_SCRIPT:
sed -f /path/to/scripts file
-r: 使用扩展正则表达式
Address:
1.StartLine,EndLine
比如1,100
$:最后一行
$-1:倒数第二行
2./RegExp/
/^root/
3./pattern1/,/pattern2/
第一次被pattern1匹配到的行开始,至第一次被pattern2匹配到的行结束中间的所有行
4.LineNumber
指定的行
5.StartLine,+N
从startline开始,向后的N行;
Command:
d:删除符合条件的行;
sed '1,2d' /etc/fstab
sed '/oot/d' /etc/fstab
sed '1,+2d' /etc/fstab 删除3行
sed '1d' /etc/fstab 只删除第一行
p:显示符合条件的行;
sed -n '/^\//p' /etc/fstab 显示以斜线开头的行
追加一行:
sed '/^\//a \# hello world' /etc/fstab
a \string:在指定的行后面追加新行,内容为string
i \string:在指定的行前面添加新行,内容为string
r FILE : 将指定的文件的内容添加至符合条件的行处
w FILE:将指定范围内的内容另存至指定的文件中
s/pattern/string/ 修饰符: 查找并替换,默认只替换每行中第一次被模式匹配到的串
加修饰符
g:全局替换
i:忽略字符大小写
s///?###,s@@@
\(\),\1,\2
把行首#换成/
sed 's/^\//#/' /etc/fstab
l...e:like...liker
love...lover
sed 's#l...e#&r#g' sed.txt
后向引用
sed 's#\(l...e\)#\1r#g' sed.txt
like...Like
love...Love
只需用到前面匹配内容的一部分时使用后向引用
sed 's#l\(..e\)#L\1#g' sed.txt
sed命令删除行首空白字符:(锚定行首,查找替换空格为什么都没有)
history | sed 's#^[[:space:]]*##g'
取出路径的父目录
/var/log
sed练习:
1.删除/etc/grub.conf文件中行首的空白符;
sed -r ‘s@1+@@g’ /etc/grub.conf
2.替换/etc/inittab文件中"id:3:initdefault:"一行中的数字为5
sed ‘s@\(id:\)[0-9]\(:initdefault:\)@\15\2@g’ /etc/inittab
3.删除/etc/inittab文件中的空白行
sed ‘/^$/d’ /etc/inittab
4.删除/etc/inittab文件中开头的#号
sed ‘s@^#@@g’ /etc/inittab
5.删除某文件中开头的#号及后面的空白字符,但要求#号后面必须有空白字符
sed -r ‘s@^#[[:space:]]+@@g’ /etc/inittab
6.删除某文件中以空白字符后面跟#类的行中的开头的空白字符及#
sed -r ‘s@2+#@@g’ /etc/inittab
7.取出一个文件路径的目录名称
echo “/etc/rc.d” | sed -r ‘s@(/.*/)[/]+/?@\1@g’
基名:
echo “/etc/rc.d” | sed -r ‘s@/.*/([/]+)/?@\1@g’
#abc
# hello world
# hi world
我的解答:
1。
[root@localhost /]# sed 's#^[[:space:]]*##g' /etc/grub.conf
1234567
2.
sed 's#(?<=\:)[^\s\:]+(?=\:)#5#' /etc/inittab 存疑
3.
[root@localhost /]# sed '/^$/d' /etc/split.txt
#abc
# hello world
#hi world
4.
[root@localhost /]# sed 's/\#*//g' /etc/split.txt
abc
hello world
hi world
5.
[root@localhost /]# sed 's/\#[[:space:]]//g' /etc/split.txt
#abc
hello world
#hi world
6.
[root@localhost /]# sed 's/.*[[:space:]]\#//g' /etc/split.txt
#abc
# hello world
hi world
7.
字符串测试:
==
!=:测试是否不等,不等为真,等为假
>
<
-n string:测试指定字符串是否为空,空为真,不空为假
-s string:测试指定字符串是否不空,不空为真,空为假
传递一个用户名参数给脚本,判断此用户的用户名跟其基本组的组名是否一致,并将结果显示出来。
if [ `id -n -u $1` == ` id -n -g $1` ];then
echo “Yiyang”
else
echo “Buyiyang”
fi
传递一个参数(单字符就行)给脚本,如参数为q,就退出脚本;否则就显示用户的参数:
#!/bin/bash
if [ $1 = ‘q’];then
echo “Quiting…”
exit 1
elif [ $1 = ‘Q’ ];then
echo “Quiting…”
exit 2
fi
bc 使用scale=2可以保留精度
echo "scale=2;111/22;" |bc
bc <<< "scale=2;111/22;"
写一个脚本:
给脚本传递三个整数,判断其中的最大数和最小数,并显示出来
MAX=0
MAX -eq $1
MAX=$1
MAX -lt $2
MAX=$2
传递3个参数给脚本,参数均为用户名,将此些用户的账号信息提取出来后放置于/tmp/testusers.txt文件中,并要求每一行行首有行号。
echo “1 $LINE” >> /tmp/testusers
循环:进入条件,退出条件
for
while
until
for 变量 in 列表; do
循环体
done
如何生成列表:
{1…100}
`seq [起始数 [步进长度]] 结束数` 注:[]可省
declare -i SUM=0 把变量声明为整型
从1加到100
#!/bin/bash
declare -i SUM=0
for I in {1..100}; do
let SUM=$[$SUM+$I]
done
echo "The sum is: $SUM"
取出行中每一行并问好。
LINES=`wc -l /etc/passwd | cut -d' ' -f1`
for I in `seq 1 $LINES`; do
echo "Hello,`head -n $I /etc/passwd | tail -1 | cut -d: -f1^`"
done
case语句及脚本选项进阶
case语句:选择结构
case SWITCH in
value1)
statement
...
;;
value2)
statement
...
;;
*)
statement
...
;;
esac
举个栗子:
#!/bin/bash
case $1 in
[0-9])
echo "A digit." ;;
[a-z])
echo "Lower." ;;
[A-Z])
echo "Upper." ;;
*)
echo "others." ;;
esac
#检查语法
[root@localhost jiaoben]# bash -n case.sh
[root@localhost jiaoben]# chmod +x case.sh
[root@localhost jiaoben]# ./case.sh a
Lower.
只接受参数start,stop,restart,status其中之一
#!/bin/bash
case $1 in
'start')
echo "start server......" ;;
'stop')
echo "stop server......" ;;
'restart')
echo "restart server......." ;;
'status')
echo "running......" ;;
*)
echo "`basename $0` {start|stop|restart|status}" ;;
esac
[root@localhost jiaoben]# ./service.sh st
service.sh {start|stop|restart|status}
写一个脚本。可以接受选项及参数,而后能获取每一个选项,及选项的参数;并能根据选项及参数做出特定的操作,比如
adminusers.sh --add tom,jerry --del tom,blair -v|–verbose -h|–help
添加用户成功即显示详细信息
#!/bin/bash
DEBUG=0
case $1 in
-v|--verbose)
DEBUG=1 ;;
esac
useradd tom &> /dev/null
[ $DEBUG -eq 1 ] && echo "Add user tom finished."
[root@localhost jiaoben]# ./addusers.sh -v
Add user tom finished.
#!/bin/bash
DEBUG=0
ADD=0
DEL=0
case $1 in
-v|--verbose)
DEBUG=1
shift ;;
-h|--help)
echo "Usage:`basename $0` --add USER_LIST --del USER_LIST -v|--verbose -h|--help"
exit 0
;;
--add)
ADD=1
USERS=$2
shift 2
;;
--del)
DEL=1
USERS=$2
shift 2
;;
*)
echo "Usage :` basename $0` --add USER_LIST --del USER_LIST -v|--verbose -h|--help"
exit 7
;;
esac
删除和添加用户可以同时使用
[root@localhost jiaoben]# ./adminusers1.sh --add tom,jerry,natasha --del tom
[root@localhost jiaoben]# ./adminusers1.sh -v --add tom,jerry,natasha --del tom
Add user tom finished.
jerry exists.
natasha exists.
Delete tom finished.
adminusers1.sh
#!/bin/bash
DEBUG=0
ADD=0
DEL=0
for I in `seq 1 $#`;do
if [ $# -gt 0 ];then
case $1 in
-v|--verbose)
DEBUG=1
shift ;;
-h|--help)
echo "Usage:`basename $0` --add USER_LIST --del USER_LIST -v|--verbose -h|--help"
exit 0
;;
--add)
ADD=1
ADDUSERS=$2
shift 2
;;
--del)
DEL=1
DELUSERS=$2
shift 2
;;
*)
echo "Usage :` basename $0` --add USER_LIST --del USER_LIST -v|--verbose -h|--help"
exit 7
;;
esac
fi
done
if [ $ADD -eq 1 ]; then
for USER in `echo $ADDUSERS | sed 's@,@ @g'`;do
if id $USER &> /dev/null; then
[ $DEBUG -eq 1 ] && echo "$USER exists."
else
useradd $USER
[ $DEBUG -eq 1 ] && echo "Add user $USER finished."
fi
done
fi
if [ $DEL -eq 1 ];then
for USER in `echo $DELUSERS | sed 's@,@ @g'`;do
if id $USER &> /dev/null; then
userdel -r $USER
[ $DEBUG -eq 1 ] && echo "Delete $USER finished."
else
[ $DEBUG -eq 1 ] && echo "$USER not exist"
fi
done
fi
#正常退出与非正常退出
[root@localhost jiaoben]# ./adminusers1.sh --help
Usage:adminusers1.sh --add USER_LIST --del USER_LIST -v|--verbose -h|--help
[root@localhost jiaoben]# echo $?
0
[root@localhost jiaoben]# ./adminusers1.sh --abc
Usage :adminusers1.sh --add USER_LIST --del USER_LIST -v|--verbose -h|--help
[root@localhost jiaoben]# echo $?
7
练习:写一个脚本showlogged.sh,其用法格式为
showlogged.sh -v -c -h| --help
其中,-h选项只能单独使用,用于显示帮助信息;-c选项时,显示当前系统上登录的所有用户数;如果同时使用了-v选项,则既显示同时登录的用户数,又显示登录的用户的相关信息。
#!/bin/bash
declare -i SHOWNUM=0
declare -i SHOWUSERS=0
for I in `seq 1 $#`;do
if [ $# -gt 0 ];then
case $1 in
-h|--help)
echo "Usage:`basename $0` -v|--verbose -h|--help -c|--count"
exit 0
;;
-v|--verbose)
let SHOWUSERS=1
shift
;;
-c|--count)
let SHOWNUM=1
shift
;;
*)
echo "Usage:`basename $0` -v|--verbose -h|--help -c|--count"
exit 8
;;
esac
fi
done
if [ $SHOWNUM -eq 1 ];then
echo "Logged users:`who | wc -l`."
fi
if [ $SHOWUSERS -eq 1 ];then
echo "They are:"
who
fi
[root@localhost jiaoben]# vim showlogged.sh
[root@localhost jiaoben]# chmod +x showlogged.sh
[root@localhost jiaoben]# ./showlogged.sh -h
Usage:showlogged.sh -v|--verbose -h|--help -c|--count
[root@localhost jiaoben]# echo $?
0
[root@localhost jiaoben]# ./showlogged.sh -v
./showlogged.sh: 第 29 行:[: 缺少 `]'
[root@localhost jiaoben]# vim showlogged.sh
[root@localhost jiaoben]# ./showlogged.sh -v
They are:
root tty1 2018-10-20 10:45
root pts/0 2018-10-21 09:18 (192.168.83.1)
root pts/1 2018-10-21 13:25 (192.168.83.1)