判断某需求是否满足,需要由测试机制来实现;
如何编写测试表达式以实现所需的测试:
(1) 执行命令,并利用命令状态返回值来判断;
0:成功
1-255:失败
#判断是否有空白行
grep "^$" /etc/rc.d/init.d/functions &> /dev/null
#查看命令状态返回值
echo $?
#判断登录用户名为centos的用户
who | grep "^centos/>"
#查看命令状态返回值
echo $?
(2) 测试表达式
test EXPRESSION
[ EXPRESSION ]
[[ EXPRESSION ]]
注意:EXPRESSION两端必须有空白字符,否则为语法错误;
bash的测试类型:
数值测试
字符串测试
文件测试
数值测试:数值比较
-eq:是否等于; [ $num1 -eq $num2 ]
-ne:是否不等于;
-gt:是否大于;
-ge:是否大于等于;
-lt:是否小于;
-le:是否小于等于;
test 2 -eq 3
echo $?
test 2 -ne 3
echo $?
字符串测试:
==:是否等于;
:是否大于;
<:是否小于;
!=:是否不等于;
=~:左侧字符串是否能够被右侧的PATTERN所匹配;
-z "STRING": 判断指定的字符串是否为空;空则为真,不空则假;
-n "STRING": 判断指定的字符串是否不为空;不空为真,不空为假;
[ tom == Tom ]
echo $?
[ tom == tom ]
echo $?
#判断是否为空
[[ -z "" ]]
echo $?
#判断是否为空
[[ -z "abc" ]]
echo $?
注意:变量做比较,万一某个变量的值为空就麻烦了;使用变量作比较记得给变量加双引号;
字符串比较,要使用[[ ]]
name=tom
#匹配字符串中是否有o这个字符
[[ $name =~ o ]]
echo $?
name=jerry
[[ $name =~ o ]]
echo $?
文件测试
存在性测试:存在则为真,否则则为假;
-a和-e都用于表示文件存在性测试,一般使用-e
-a /PATH/FILE
-e /PATH/FILE
#查看文件是否存在
[ -e /etc/fstab ]
echo $?
存在性及类型测试
-b FILE:是否存在并且为块设备文件;
-c FILE:是否存在并且为字符设备文件;
-d FILE:是否存在并且为目录文件;
-f FILE:是否存在并且为普通文件;
-h FILE或-L FILE:是否存在并且为符号链接文件;
-p FILE:是否存在且为命名管道文件;
-S FILE:是否存在且为套接字文件;
#判断是否存在且是块设备
[ -b /dev/sda ]
echo $?
#查看文件类型
file /dev/sda
[ -b /dev/sdb ]
echo $?
文件权限测试:
-r FILE:是否存在并且对当前用户可读;
-w FILE:是否存在并且对当前用户可写;
-x FILE:是否存在并且对当前用户可执行;
特殊权限测试:
-u FILE:是否存在并且拥有suid权限;
-g FILE:是否存在并且拥有sgid权限;
-k FILE:是否存在并且用用stlcky权限;
#是否存在并且拥有suid权限
[ -u /usr/bin/passwd ]
echo $?
文件是否有内容:
-s FILE:是否有内容;
touch /tmp/hello
#新建的文件肯定没有内容
[ -s /tmp/hello ]
echo $?
文件时间戳测试:
-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
测试文件是否为属主,并且可读
[ -O FILE ] && [ -r FILE ]
[ -O /etc/fstab ] && [ -r /etc/fstab ]
echo $?
第二种方式:
[ EXPRESSION1 -a EXPRESSION2 ]
[ EXPRESSION1 -o EXPRESSION2 ]
[ ! EXPRESSION1 ]
[ -O /etc/fstab -a -x /etc/fstab ]
echo $?
练习:将当前主机名称保存至hostName变量中;
主机名如果为空,或者为localhost.localdomain,则将其设置为www.abc.com;
hostName=$(hostname)
[ -z "$hostName" -o "$hostName" == "localhost.localdomain" ] && hostname www.abc.com
hostname
脚本的状态返回值:
默认是脚本中执行的最后一条命令的状态返回值;
自定义状态退出状态码;
exit [n]:n为自己指定的状态码; 0:成功,1-255:失败;
注意:shell进程遇到exit时,即会终止,因此,整个脚本执行即为结束;
id user1 &> /dev/null && exit 0 || useradd user1
#像/etc,/var传递给命令的参数,称之为位置参数
ls /etc /var
位置参数变量
myscript.sh argu1 argu2
引用方式:
$1,$2,....,${10},${11},...
给shell脚本传递参数
以下使用vim编辑器编写sum.sh文件如下:
#!/bin/bash
echo $[$1+$2]
执行以上脚本
bash sum.sh 10 20
轮替:
shift [n]:位置参数轮替;
shift.sh文件创建
#/bin/bash
echo "First pos args:$1"
#踢掉了第一个参数
shift
echo "First pos args:$1"
执行以上脚本
bash shift.sh one two
修改shift.sh文件
#/bin/bash
echo "First and second pos args:$1,$2"
#踢掉前两个参数
shift 2
echo "Third pos args:$1"
执行以上脚本
bash shift.sh one two three
练习:写一个脚本,通过命令传递两个文本文件路径给脚本,计算其空白行数之和;
lines.sh文件:
#!/bin/bash
linecount1=$(grep "^$" $1 | wc -l)
linecount2=$(grep "^$" $2 | wc -l)
echo "total black lines:$[$linecount1+$linecount2]"
执行以上脚本
bash lines.sh /etc/fstab /etc/rc.d/init.d/functions
$0
:脚本文件路径本身;
$#
:脚本参数的个数;
$*
:所有参数;("hello" "hi" "toyou")
$@
:所有参数;("hello hi toyou")
pos.sh文件如下:
#!/bin/bash
echo "脚本文件本身:$0"
echo "只取脚本文件名:$(basename $0)"
echo $1,$2
echo "脚本参数个数:$#"
echo $*
echo $@
执行以上脚本:
chmod +x pos.sh
./pos.sh hello hi toyou
修改之前lines.sh文件如下:
#!/bin/bash
[ $# -lt 2 ] && echo "至少需要两个参数" && exit 1
linecount1=$(grep "^$" $1 | wc -l)
linecount2=$(grep "^$" $2 | wc -l)
echo "total black lines:$[$linecount1+$linecount2]"
执行以上脚本:
chmod +x lines.sh
./lines.sh /etc/fstab
单分支语句:
if 测试条件;
then
代码分支
fi
双分支的if语句:
if 测试条件;then
条件为真时执行分支
else
条件为假时执行的分支
fi
示例:通过参数传递一个用户名给脚本,此用户不存在时,则添加之;
创建useradd.sh文件:
#!/bin/bash
if [ $# -lt 1 ];then
echo "请输入需要创建的用户名"
exit 2
fi
if ! grep "^$1\>" /etc/passwd &> /dev/null; then
useradd $1
echo $1 | passwd --sdtin $1 &> /dev/null
echo "Add user $1 finished."
else
echo "用户已经存在!"
fi
~
执行以上脚本
chmod +x useradd.sh
./useradd.sh zhangsan
echo $?
read [option]... [name]...
-p 'PROMPT'
-t TIMEOUT
#read是一个内嵌命令,它也有外部命令的实现
type read
#read后面的name是个变量,会等待接收用户键盘输入内容赋值给name变量
read name
#输出变量信息
echo $name
#使用-p代表PROMPT提示信息
read -p "请输入用户名:" name
echo $name
#-t 5代表5秒钟不操作,则自动退出输入
read -t 5 -p "请输入用户名:" name
示例
#!/bin/bash
read -p "请输入用户名:" name
[ -z "$name" ] && echo "请输入用户名!" && exit 2
read -p "请输入密码(默认为123456):" pwd
[ -z "$pwd" ] && pwd="123456"
if id $name &> /dev/null;then
echo "$name 已经存在!"
else
useradd $name
echo $pwd | passwd --stdin $name
echo "Add User $name finished."
fi
bash -n /path/to/some_script
bash -x /path/to/some_script
例如下面的练习1使用调试执行
1、通过命令行参数给定两个数字,输出其中较大的数值;
#!/bin/bash
declare -i max
if [ $# -lt 2 ]; then
echo "至少要两个参数!"
fi
if [ $1 -gt $2 ];then
max=$1
else
max=$2
fi
echo "max number:$max."
#调试执行
bash -x big.sh 5 10
2、通过命令行参数给定一个用户名,判断其ID号是偶数还是奇数;
3、通过命令行参数给定两个文本文件名,如果某文件不存在,则结束脚本执行; 都存在时返回每个文件的行数,并说明其中行数较多的文件;
4、写一个脚本,完成如下功能:
(1) 列出当前系统识别到的所有磁盘设备;
(2) 如磁盘数量为1,则显示其空间使用信息;
否则,则显示最后一个磁盘上的空间使用信息;
#!/bin/bash
disks=$(fdisk -l /dev/[sh]d[a-z] | grep -o "磁盘 /dev/[hs]d[a-z]" | wc -l)
if [ $disks -eq 1 ];then
fdisk -l /dev/[hs]da
else
fdisk -l /dev/[sh]d[a-z] | grep -o "磁盘 /dev/[hs]d[a-z]" | tail -1 | cut -d' ' -f2
fi
5、接收用户输入磁盘名称,获取磁盘名称的信息
#!/bin/bash
read -p "请输入磁盘名称:" diskfile
[ -z $diskfile ] && echo "必须输入磁盘名称!" && exit 2
if fdisk -l | grep "磁盘 $diskfile" &> /dev/null;then
fdisk -l $diskfile
else
echo "错误的磁盘名称"
exit 2
fi
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。