bash脚本
1、终端打印
1、单双引号(echo)
双引号:
①在双引号里面打不出!

②双引号,可以在文本中使用“;”,“;”在bash中被用作命令定界符。

单引号:
变量替换在单引号中无效。

2、printf:不会自动添加换行符,要手动添加

如下:

结果:

3、补充:
echo 要使用转义系列需要加e,!号除外

2、变量和环境变量
脚本语言通常不需要在使用变量之前声明变量类型,直接赋值就可以了。
Bash中,每一个变量的值都是字符串,无论变量赋值时有没有用引号,值都会以字符串形式存储。
1、查看某个进程的环境变量
env查看所有的环境变量 cat /proc/$PID/environ

有很多,截取一点,其中的环境变量用null字符"\0"连接,要想每行显示一个,可以将"\0"转化为"\n"。如下

2、变量赋值与引用
var=value(等号两边没有空格 var = value是错误的) 如果,value中不包含任何空白字符,就不需要用引号 变量名前加$就表示引用,可以在双引号中引用变量


环境变量是由父进程继承过来的,要用export来设置,设置后从当前shell脚本任务执行的应用程序都会继承这个变量。
比如PATH这个环境变量,就是查找文件时候的搜索路径,要在PATH中添加一条新的路径
PATH="PATH:/home/user/bin" export PATH

使用单引号时变量不会被引用。
检测是否为超级用户:

数值比较 -eq:是否等于; [ $num1 -eq $num2 ] -ne:是否不等于; -gt:是否大于; -ge:是否大于等于; -lt:是否小于; -le:是否小于等于; 字符串测试: ==:是否等于; >:是否大于; <:是否小于; !=:是否不等于; =~:左侧字符串是否能够被右侧的PATTERN所匹配; -z "STRING":判断指定的字串是否为空;空则为真,不空则假; -n "STRING":判断指定的字符串是否不空;不空则真,空则为假;
3、使用shell进行数学运算
算数操作用let、(())和[],bc是专门做运算的命令

使用let运算的后面的变量引用不用加$
计算1加到100的和:

自加let no1++ 或 let no+=6 自减let no1-- 或 let no-=6
[]的使用方法类let,(())也是。

bc是个高级的工具,可以计算浮点数和高级函数,以上都不支持浮点计算。

4、条件判断式
if [ ]; then command; fi 或: if [ ];then command1; else command2; fi 或: if [ ] ;then command; elif [ ];then command2; else command3; fi
通过参数传递一个用户名给脚本,此用户不存时,则添加之;且用户名为密码:

另外一种方法

练习2:通过命令行参数给定一个用户名,判断其ID号是偶数还是奇数;

练习3:通过命令行参数给定两个文本文件名,如果某文件不存在,则结束脚本执行;都存在时返回每个文件的行数,并说明其中行数较多的文件;

示例:脚本参数传递一个文件路径给脚本,判断此文件的类型;
#!/bin/bash # if [ $# -lt 1 ]; then echo "At least on path." exit 1 fi if ! [ -e $1 ]; then echo "No such file." exit 2 fi if [ -f $1 ]; then echo "Common file." elif [ -d $1 ]; then echo "Directory." elif [ -L $1 ]; then echo "Symbolic link." elif [ -b $1 ]; then echo "block special file." elif [ -c $1 ]; then echo "character special file." elif [ -S $1 ]; then echo "Socket file." else echo "Unkown." fi 注意:if语句可嵌套; 练习:写一个脚本 (1) 传递一个参数给脚本,此参数为用户名; (2) 根据其ID号来判断用户类型: 0: 管理员 1-999:系统用户 1000+:登录用户 #!/bin/bash # [ $# -lt 1 ] && echo "At least on user name." && exit 1 ! id $1 &> /dev/null && echo "No such user." && exit 2 userid=$(id -u $1) if [ $userid -eq 0 ]; then echo "root" elif [ $userid -ge 1000 ]; then echo "login user." else echo "System user." fi 练习:写一个脚本 (1) 列出如下菜单给用户: disk) show disks info; mem) show memory info; cpu) show cpu info; *) quit; (2) 提示用户给出自己的选择,而后显示对应其选择的相应系统信息; #!/bin/bash # cat << EOF disk) show disks info mem) show memory info cpu) show cpu info *) QUIT EOF read -p "Your choice: " option if [[ "$option" == "disk" ]]; then fdisk -l /dev/[sh]d[a-z] elif [[ "$option" == "mem" ]]; then free -m elif [[ "$option" == "cpu" ]];then lscpu else echo "Unkown option." exit 3 fi
5、循环执行
bash脚本:
for循环
while循环
until循环
for循环:
两种格式:
(1) 遍历列表
(2) 控制变量
遍历列表:
for VARAIBLE in LIST; do
循环体
done
进入条件:只要列表有元素,即可进入循环;
退出条件:列表中的元素遍历完成;
LISTT的生成方式:
(1) 直接给出;
(2) 整数列表
(a) {start..end}
如:{1..10}
(b) seq [start [incremtal]] last
如: seq 6 16 生成从6到16的数字列表,可以指定步长。 seq 1 2 6
(3) 返回列表的命令
(4) glob
(5) 变量引用
$@, $*
...
示例:求100以内所有正整数之和;
#!/bin/bash
#
declare -i sum=0
for i in {1..100}; do
echo "\$sum is $sum, \$i is $i"
sum=$[$sum+$i]
done
echo $sum
示例:判断/var/log目录下的每一个文件的内容类型
#!/bin/bash
#
for filename in /var/log/*; do
if [ -f $filename ]; then
echo "Common file."
elif [ -d $filename ]; then
echo "Directory."
elif [ -L $filename ]; then
echo "Symbolic link."
elif [ -b $filename ]; then
echo "block special file."
elif [ -c $filename ]; then
echo "character special file."
elif [ -S $filename ]; then
echo "Socket file."
else
echo "Unkown."
fi
done
练习: 1、分别求100以内所有偶数之和,以及所有奇数之和;

2、计算当前系统上的所有用的id之和;

示例:求100以内所有正整数之和; #!/bin/bash # declare -i sum=0 declare -i i=1 until [ $i -gt 100 ]; do let sum+=$i let i++ done echo $sum #!/bin/bash # declare -i sum=0 declare -i i=1 while [ $i -le 100 ]; do let sum+=$i let i++ done echo $sum while: while CONDITION; do 循环体 循环控制变量修正表达式 done 打印九九乘法表;

循环控制:
break:停止指定层循环 continue:跳过循环体中的剩余命令。

case
示例1:显示一个菜单给用户;
cpu) display cpu information
mem) display memory information
disk) display disks information
quit) quit
要求:(1) 提示用户给出自己的选择;
(2) 正确的选择则给出相应的信息;否则,则提示重新选择正确的选项;
#!/bin/bash
#
cat << EOF
cpu) display cpu information
mem) display memory infomation
disk) display disks information
quit) quit
===============================
EOF
read -p "Enter your option: " option
while [ "$option" != "cpu" -a "$option" != "mem" -a "$option" != "disk" -a "$option" != "quit" ]; do
echo "cpu, mem, disk, quit"
read -p "Enter your option again: " option
done
if [ "$option" == "cpu" ]; then
lscpu
elif [ "$option" == "mem" ]; then
free -m
elif [ "$option" == "disk" ]; then
fdisk -l /dev/[hs]d[a-z]
else
echo "quit"
exit 0
fi
case语句的语法格式:
case $VARAIBLE in
PAT1)
分支1
;;
PAT2)
分支2
;;
...
*)
分支n
;;
esac
case支持glob风格的通配符:
*:任意长度的任意字符;
?:任意单个字符;
[]:范围内任意单个字符;
a|b:a或b;
示例:写一个服务框架脚本;
$lockfile, 值/var/lock/subsys/SCRIPT_NAME
(1) 此脚本可接受start, stop, restart, status四个参数之一;
(2) 如果参数非此四者,则提示使用帮助后退出;
(3) start,则创建lockfile,并显示启动;stop,则删除lockfile,并显示停止;restart,则先删除此文件再创建此文件,而后显示重启完成;status,如果lockfile存在,则显示running,否则,则显示为stopped.
#!/bin/bash
#
# chkconfig: - 50 50
# description: test service script
#
prog=$(basename $0)
lockfile=/var/lock/subsys/$prog
case $1 in
start)
if [ -f $lockfile ]; then
echo "$prog is running yet."
else
touch $lockfile
[ $? -eq 0 ] && echo "start $prog finshed."
fi
;;
stop)
if [ -f $lockfile ]; then
rm -f $lockfile
[ $? -eq 0 ] && echo "stop $prog finished."
else
echo "$prog is not running."
fi
;;
restart)
if [ -f $lockfile ]; then
rm -f $lockfile
touch $lockfile
echo "restart $prog finished."
else
touch -f $lockfile
echo "start $prog finished."
fi
;;
status)
if [ -f $lockfile ]; then
echo "$prog is running"
else
echo "$prog is stopped."
fi
;;
*)
echo "Usage: $prog {start|stop|restart|status}"
exit 1
esac
6、函数
过程式编程:代码重用
模块化编程
结构化编程
把一段独立功能的代码当作一个整体,并为之一个名字;命名的代码段,此即为函数;
注意:定义函数的代码段不会自动执行,在调用时执行;所谓调用函数,在代码中给定函数名即可;
函数名出现的任何位置,在代码执行时,都会被自动替换为函数代码;
语法一:
function f_name {
...函数体...
}
语法二:
f_name() {
...函数体...
}
函数的生命周期:每次被调用时,创建函数,返回时终止,即函数代码引用完了,bash脚本每次都有一个状态返回值,函数也有返回值。在函数中使用echo打印的返回值,也有状态返回值。其状态返回结果为函数体中运行的最后一条命令的状态结果;
自定义状态返回值,需要使用:return(终止),相当于exit。
return [0-255]
0: 成功
1-255: 失败
示例:给定一个用户名,取得用户的id号和默认shell;
#!/bin/bash
#
userinfo() {
if id "$username" &> /dev/null; then
grep "^$username\>" /etc/passwd | cut -d: -f3,7
else
echo "No such user."
fi
}
username=$1
userinfo
username=$2
userinfo
示例2:服务脚本框架
#!/bin/bash
#
# chkconfig: - 50 50
# description: test service script
#
prog=$(basename $0)
lockfile=/var/lock/subsys/$prog
start() {
if [ -f $lockfile ]; then
echo "$prog is running yet."
else
touch $lockfile
[ $? -eq 0 ] && echo "start $prog finshed."
fi
}
stop() {
if [ -f $lockfile ]; then
rm -f $lockfile
[ $? -eq 0 ] && echo "stop $prog finished."
else
echo "$prog is not running."
fi
}
status() {
if [ -f $lockfile ]; then
echo "$prog is running"
else
echo "$prog is stopped."
fi
}
usage() {
echo "Usage: $prog {start|stop|restart|status}"
}
case $1 in
start)
start ;;
stop)
stop ;;
restart)
stop
start ;;
status)
status ;;
*)
usage
exit 1 ;;
esac
函数返回值:
函数的执行结果返回值:
(1) 使用echo或printf命令进行输出;
(2) 函数体中调用的命令的执行结果;
函数的退出状态码:
(1) 默认取决于函数体中执行的最后一条命令的退出状态码;
(2) 自定义:return
函数可以接受参数:
传递参数给函数:
在函数体中当中,可以使用$1,$2, ...引用传递给函数的参数;还可以函数中使用$*或$@引用所有参数,$#引用传递的参数的个数;
在调用函数时,在函数名后面以空白符分隔给定参数列表即可,例如,testfunc arg1 arg2 arg3 ...
示例:添加10个用户,
添加用户的功能使用函数实现,用户名做为参数传递给函数;
#!/bin/bash
#
# 5: user exists
addusers() {
if id $1 &> /dev/null; then
return 5
else
useradd $1
retval=$?
return $retval
fi
}
for i in {1..10}; do
addusers ${1}${i}
retval=$?
if [ $retval -eq 0 ]; then
echo "Add user ${1}${i} finished."
elif [ $retval -eq 5 ]; then
echo "user ${1}${i} exists."
else
echo "Unkown Error."
fi
done
练习:写一个脚本;
使用函数实现ping一个主机来测试主机的在线状态;主机地址通过参数传递给函数;
主程序:测试172.16.1.1-172.16.67.1范围内各主机的在线状态;
练习:写一个脚本;
打印NN乘法表;
变量作用域:
局部变量:作用域是函数的生命周期;在函数结束时被自动销毁;
定义局部变量的方法:local VARIABLE=VALUE
本地变量:作用域是运行脚本的shell进程的生命周期;因此,其作用范围为当前shell脚本程序文件;
示例程序:
#!/bin/bash
#
name=tom
setname() {
local name=jerry
echo "Function: $name"
}
setname
echo "Shell: $name"
函数递归:
函数直接或间接调用自身;
10!=10*9!=10*9*8!=10*9*8*7!=...
n
n*(n-1)!=n*(n-1)*(n-2)!=
#!/bin/bash
#
fact() {
if [ $1 -eq 0 -o $1 -eq 1 ]; then
echo 1
else
echo $[$1*$(fact $[$1-1])]
fi
}
fact $1
1,1,2,3,5,8,13,21,...
#!/bin/bash
#
fab() {
if [ $1 -eq 1 ]; then
echo -n "1 "
elif [ $1 -eq 2 ]; then
echo -n "1 "
else
echo -n "$[$(fab $[$1-1])+$(fab $[$1-2])] "
fi
}
for i in $(seq 1 $1); do
fab $i
done
echo
原创文章,作者:N24_yezi,如若转载,请注明出处:http://www.178linux.com/61364


评论列表(1条)
bash 相关的知识总结的很好,如能附加一些特殊变量的说明就更全面了