bash应该是目前Linux上最流行的shell脚本解释程序了,只要你在linux上工作,并且希望自己能够工作得更愉悦,那么你应该熟悉最基本的bash编程,因为它将给你的工作带来足够的幸福感。本文将总结一些我自己平时使用的bash基本编程知识,和大家分享,也便于自己查询。
变量
bash的变量名是区分大小写的,并且变量名首字符不能是数字
变量定义与赋值
aaa=123
这里需要注意定义变量时等号前后都不能有空格,必须紧靠着写。虽然等号后面有空格的情况,语法可能不会出错,但结果绝对是错误的。
变量拼接
bbb=${aaa}123
很多时候,我们可能需要用一些变量、常量字符串等来拼接出一个新的变量,这时需要注意用来拼接的变量可能需要加上{},否则可能会出现变量识别错误从而找不到变量的情况。这种情况,我倾向于所有变量一股脑的全加上{}。
条件判断
if条件表达中长涉及到的比较有字符串、整数和文件属性比较等。
if语句格式有:
if [ expr ] ; then
do something
fi
if [ expr ] ; then
do something
else
do something
fi
if [ expr ] ; then
do something
elif [ expr ] ; then
do something
else
so something
fi
if语句和其他语言(c,java)相比,是行不同但神似。then关键可以另起一行,那样条件表达式后的分号就可以省略了。这里最需要注意的是 " [ " 和 " ] "前后至少需要一个空格来分割。
1、整数比较
整数大小比较涉及的操作符有—— -lt、-le、-eq、-gt、-ge和 -ne。
例子:
-lt 大于
-gt 小于
-le 小于等于
-ge 大于等于
-ne 不等于
-eq 等于
a=1
b=2
if [ $a -lt $b ] ; then
echo "a < b"
else
echo "a >= b"
fi
if [ $a -ne 3 ] ; then
echo "a != 3"
else
echo "a == 3"
fi
if [ 1 -gt 3 ] ; then
echo "1 > 3"
else
echo "1 <= 3"
fi
使用整数大小比较的6个操作符时,涉及到的两个操作数将会作为数值来处理,而不是字符串,即使你使用双引号将比较对象给引起来,也是如此。
三种使用格式
单分支的if语句:
if 测试条件; then
选择分支
fi
表示条件测试状态返回值为值,则执行选择分支;
if ! id $username &> /dev/null; then
useradd $username
fi
练习:写一个脚本,接受一个参数,这个参数是用户名;如果此用户存在,则显示其ID号;
双分支的if语句:
if 测试条件; then
选择分支1
else
选择分支2
fi
两个分支仅执行其中之一。
通过命令行给定一个文件路径,而后判断:
如果此文件中存在空白行,则显示其空白行的总数;
否则,则显示无空白行;
if grep "^[[:space]]*$" $1 &> /dev/null; then
echo "$1 has $(grep "^[[:space]]*$" $1 | wc -l) blank lines."
else
echo "No blank lines"
fi
注意:如果把命令执行成功与否当作条件,则if语句后必须只跟命令本身,而不能引用。
多分支的if语句:
if 条件1; then
分支1
elif 条件2; then
分支2
elif 条件3; then
分支3
...
else
分支n
fi
传递一个用户名给脚本:
如果此用户的id号为0,则显示说这是管理员
如果此用户的id号大于等于500,则显示说这是普通用户
否则,则说这是系统用户;
2、字符串比较
字符串比较可能用到的操作符有—— =、!=、>、<、-n和-z。
例子:
s1=aaa
s2=bbb
if [ $s1 \< $s2 ] ; then
echo "$s1 < $s2"
else
echo "$s1 >= $s2"
fi
if [[ $s1 < $s2 ]] ; then
echo "$s1 < $s2"
else
echo "$s1 >= $s2"
fi
if [ $s1 = $s2 ] ; then
echo "$s1 == $s2"
else
echo "$s1 != $s2"
fi
if [ -n $s1 ] ; then
echo $s1
fi
用于字符串大小比较的>和<两个操作符比较特别,在[ ]中书写时需要转义,否则可以使用` `来替代[ ]。不转义,>和<会被解释为IO重定向操作。其次,if语句体不能为空,必须至少做一件事情。
操作符-n 用于判断字符串不为空,即长度不为0。-z判断字符串为空,即长度为0
for循环
常用的for循环有两种主要形式
形式一
for e in [list]
do
do something
done
这种格式的for常用来遍历一个list集合中的所有元素,并加以处理。比如:
1、遍历一个目录中的所有文件
for file in `ls dir`
do
echo $file
done
2、遍历一个给定的集合
list="a b c d e f g"
for e in $list
do
echo $e
done
for in格式在遍历集合时,其实是根据空白字符来分隔字符串,取得每个元素的,上例中的`ls dir`和$list得到的都是一个带空白字符的字符串。
形式二
for ((i = 0; i < n; i++))
do
do something
done
这一种for的形式和C语言基本一致,只是需要双括号罢了,它更擅长做确定次数的循环计算。比如:
for ((i = 0; i < 10; i++))
do
echo $i
done
练习:写一脚本
1、添加10个用户:tuser601-tuser610
如果用户不存在,才添加,并以绿色显示添加成功;如果存在,则以红色显示已经有此用户;
2、显示一共添加了多少个用户;
#!/bin/bash
#
declare -i count=0
for i in {501..510}; do
if id tuser$i &> /dev/null; then
echo -e "\033[31mtuser$i\033[0m exists."
else
useradd tuser$i
echo -e "add user \033[32mtuser$i\033[0m successfully."
let count++
fi
done
echo "Total add $count users."
练习:写一个脚本
传递用户名给脚本
1、判断此用户的shell是否为/bin/bash,如果是,则显示此用户为basher
2、否则,则显示此用户为非basher
#!/bin/bash
#
userShell=`grep "^$1\>" /etc/passwd | cut -d: -f7`
if [ "$userShell" == '/bin/bash' ]; then
echo "basher"
else
echo "not basher"
fi
我们
扫描172.16.250.0/16内的所有主机;在线的,使用绿色显示;不在线,使用红色显示;
最后分别显示:在线和不在线各有多少主机;
我们要给其加上一个执行权限
也可以用bash走下测试
bash -n 文件名 测试语法错误
bash -x 文件名 直接交给bash运行 不用加权限
case语句
case语句相当于绝大多数语言里的switch语句。这玩意除了具备if-elif的功能外,还支持通配符,这个相当有用。我们直接看例子。
例子:
url=www.tmall.com
case $url in
www.taobao.com) echo 1;;
*.taobao.com) echo 2;;
*.tmall.com) echo 3;;
www.tmall.com) echo 4;;
*) echo 5;;
esac
上例中条件分支不光有常量字符串,还有含通配符的字符串,这一点用来进行模式匹配非常便利。其次,需要注意case语言在匹配的过程中是从第一个开始逐一匹配,所有上例的输出结果是3,而不是精确匹配的4
函数
函数定义
function hello()
{
echo "hello world"
}
函数定义实用关键字function,函数名后面的括号可有可无。
函数调用
无参数的函数调用只需要给出函数名就ok了,上面定义的函数直接用hello调用即可。有参数的函数,只需要将参数依次在函数名后面给出即可,如:func_name arg1 arg2。
函数参数
函数调用的时候可以给函数传递参数,那么函数体中又如何获取这些参数呢? 函数参数的获取和脚本程序参数的获取一致,都是通过$1、$2等来取得。比如:
function add()
{
n=$1
m=$2
echo $((n + m))
}
调用add 1 2,将输出3。
在函数中,可以通过$#的值来判断函数调用的时候,传递了几个参数。
bash函数里很少使用return这种方式来返回值。不过可以这样调用函数来获取计算结果,比如:
res=`add 1 2`
变量res的值就是3了。注意上面不是单引号,而是数字1旁边的字符。
字符串处理
字符串处理差不多是整个计算机世界里做得最频繁的一件事情了。玩C语言的人很多事情都是在编写字符串处理程序。玩java的人大多数时候虽然不用自己去编写字符串处理程序,但也基本总是在调用字符串处理方法。linux其实有着非常强大的工具让我们去做字符串处理,不熟悉之前,每个工具貌似长得都非常复杂的样子。这里简单的总结一下自己使用过的字符串相关的东东。
1、求子串
str=abcdefg
echo ${str:2:3} 将得到bcd,表达式中的2代表偏移量,3代表长度。
2、求字符串长度
str=123456
echo ${#str}
3、字符串替换
${变量/pattern/xx} 将变量中的第一个匹配替换为xx。
${变量//pattern/xx} 将变量中的所有匹配替换为xx。
str=aaabbbccc
echo ${str/aaa/xxx}
echo ${str/a/x}
有关字符串的处理,有着很多的工具,比如:你可以使用cut, awk等程序去拆分一个字符串等。
整数运算
整数运算一般使用$(( expr ))来进行。比如:
echo $((1 + 2))
a=1
echo $((a + 2))
echo $((a++))
echo $((++a))
b=2
echo $(((a + b) / 2))
可以看到只需要将计算表达式塞到$(())中就可以了,参与计算的变量并不需要$符号。整数运算涉及到的运算符有:++ 、--、+、-、*、/、%、+=、
写一个脚本,使用格式:
script.sh {start|stop|restart|status}
1) start: 创建/var/lock/subsys/script.sh
2) stop: 删除此文件
3) restart: 先删除文件,再创建文件
4) status: 如文件存在,显示running,否则,显示stopped
#!/bin/bash
#
srv=`basename $0`
lockFile="/var/lock/subsys/$srv"
[ $# -lt 1 ] && echo "Usage: $srv {start|stop|restart|status}" && exit 4
[ $UID -ne 0 ] && echo "Only root." && exit 5
case $1 in
start)
if [ -f $lockFile ]; then
echo "$srv is running."
exit 7
else
touch $lockFile
[ $? -eq 0 ] && echo "Starting $srv OK."
fi
;;
stop)
if [ -f $lockFile ]; then
rm -f $lockFile
[ $? -eq 0 ] && echo "Stopping $srv OK."
else
echo "$srv is stopped yes."
exit 6
fi
;;
restart)
if [ -f $lockFile ];then
rm -f $lockFile
[ $? -eq 0 ] && echo "Stopping $srv OK."
else
echo "$srv is stopped yet."
fi
touch $lockFile
[ $? -eq 0 ] && echo "Starting $srv OK."
;;
status)
if [ -f $lockFile ];then
echo "$srv is running."
else
echo "$srv is stopped."
fi
;;
*)
echo "Usage: $srv {start|stop|restart|status}" && exit 9
esac
转载于:https://blog.51cto.com/9025736/1534098