首页 > 网络 > 云计算 >

初级bash-shell脚本编写和练习

2017-08-16

初级bash-shell脚本编写和练习。条件测试语法有两种书写模式,一种是[ expression ], 另一种是[[ expression ]],为了在书写条件测试的过程中,不让大家将两种格式相互混淆,那么在这里我只讲一种格式,也就是第一种格式[ ]。因为第一种格式在书写过程中基本不会写错

条件测试语法有两种书写模式,一种是[ expression ], 另一种是[[ expression ]],为了在书写条件测试的过程中,不让大家将两种格式相互混淆,那么在这里我只讲一种格式,也就是第一种格式[ ]。因为第一种格式在书写过程中基本不会写错,而第二种格式经常会写错,且第一种格式在很多服务的启动脚本中经常看到,因此应用广。那么为了降低bash编程的门槛,在这里我只讲解第一种,如果对shell编程感兴趣的同学,可以查看《shell脚本编程大全》一书

判断某需求是否满足,需要由测试机制来实现,下面我们就讲讲如何编写测试表达式来实现所需的测试

条件测试的状态返回值和书写格式

1:执行命令,利用状态返回值来判断

0:成功

1-255:失败

2:测试表达式

test expression

[ expression ] 常用

[[ expression ]]

bash的测试类型

数值测试

字符串测试

文件测试

数值测试:数值比较

-eq:是否等于 [ $num1 -eq $num2 ]

-ne:是否不等于 [ $num1 -ne $num2 ]

-gt:是否大于 [ $num1 -gt $num2 ]

-ge:是否大于等于 [ $num1 -ge $num2 ]

-lt:是否小于 [ $num1 -lt $num2 ]

-le:是否小于等于 [ $num1 -le $num2 ]

字符串测试:字符比较

==:是否等于

>:是否大于

<:是否小于

!=:是否不等于

=~:左侧字符串是否能够被右侧的pattern所匹配

-z“string”:判断指定的字符串是否为空 ,空则为真,不空则假

-n“string”:判断指定的字符串是否为不空 ,不空则为真,不空则假

注意:

(1)字符串要加引号

(2)在做字符串的比较的时候,格式如下:

if [ "$VARIABLE" == "$VARIABLE" -a "$VARIABLE" == "cpu" ];then 需要在运算符号两边有空格,并且使用双引号将字符串包裹起来,这样即使是变量也可以替换

文件测试

存在性测试

-a file

-e file

文件的存在性测试,存在为真,否则为假

文件类型测试

-b file:是否存在并且为块设备文件

-c file:是否存在并且为字符设备文件

-d file:是否存在并且为目录文件

-f file:是否存在并且为普通文件

-h/l file:是否存在并且为符号链接文件

-p file:是否存在并且为管道文件

-S file:是否存在并且为套接字文件

文件是否有内容

-s file:是否存在并且有内容

变量是否有为空,为空则为真

-z ""$VARIABLE"

文件的时间戳测试

-N file:文件自从上次被读取后是否修改过

从属关系测试

-O file:当前用户是否为文件的属主

-G file:当前用户是否属于文件的属组

双目测试

file1 -ef file2:是否为同一文件系统上的指向同一iNode的硬链接

file1 -nt file2:file1 是否新于file2

file1 -ot file2:file1 是否旧于file2

组合条件测试

逻辑运算

第一种方式

COMMAND1 && COMMAND2

COMMAND1 | | COMMAND2

! COMMAND

[-O file]&&[-r file]

第二种方式

[ expression -a expression ]:与运算

[ expression -o expression ]:或运算

! expression

例如:[ -O file -a -x file ]

脚本的状态返回值

1:默认是脚本执行的最后一条命令的返回值

2:自定义状态退出状态码

exit [n]:n为自己指定的状态码

注意:shell进程遇到exit时候,会立即终止,整个脚本执行结束

过程式编程语言的代码执行顺序

顺序执行:逐条运行

选择执行:

代码存在一个或多个分支,只执行其中一个

代码有一个分支:条件满足时才会执行

两个或以上的分支:只会执行其中一个满足条件的分支

循环执行:

代码片段(循环体)要执行0,1或多个来回

一,选择执行:

单分支的if语句

if 测试条件;then

如果满足条件就执行这里的代码

fi

双分支的if语句

if 测试条件;then

如果满足条件就执行这里的代码

else

如果不满足条件就执行这里的代码

fi

练习1:通过参数传递一个用户名给脚本,此用户不存在,则添加,密码与用户名相同

#!/bin/bash

if [ $# -lt 1 ];

then

echo "please send argument"

exit 1

fi #如果没有传递参数,直接退出

if grep "^$1\>" /etc/passwd &>/dev/null;then #输入一个参数即用户名与/etc/ passwd进行匹配,

若相同则

echo "user $1 exists

else #若不相同则创建新用户

useradd $1

echo $1 | passwd --stdin $1 &>/dev/null #将用户名标准输出到密码,/dev/null表示不在屏幕输出

echo "add user $1"

fi

练习2:通过参数传递一个用户名给脚本,此用户存在,则删除用户以及其家目录和邮件目录

#!/bin/bash

# description

if [ $# -lt 1 ];then

echo "please send a argument."

exit 1

fi

if id -u $1 &> /dev/null;then #输入一个参数即用户名, id -u可用来检测用户是否存在

userdel -r $1

echo "delete user $1"

else

echo "user $1 doesn&#39;t exists"

fi

练习3:通过命令行参数给定两个数字,输出其中最大的数值

方法1

#!/bin/bash

#如果没有传递参数,直接退出

if [ $# -lt 2 ];

then

echo "please send two arguments"

exit 1

fi

if [ $1 -eq $2 ];then

echo "$1 equals to $2"

exit 1

fi

if [ $1 -gt $2 ];then

echo "The big one is $1"

else

echo "The big one is $2"

fi

方法2

#!/bin/bash

#如果没有传递参数,直接退出

if [ $# -lt 2 ];

then

echo "please send argument"

exit 1

fi

declare -i max=$1

if [ $max -lt $2 ];then

max=$2

fi

echo "The big one is $max"

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

#!/bin/bash

#如果没有传递参数,直接退出

if [ $# -lt 1 ];

then

echo "please send argument"

exit 1

fi

if id -u $1 &> /dev/null;then

idNum=$(id -u $1)

let s=$idNum%2 # 判断余数是0还是1,如果是0,那么就是偶数,如果是1,就是奇数

if [ $s -eq 0 ];then

echo "$1&#39;IDNum is $idNum and oven"

else

echo "$1&#39;IDNum is $idNum and odd"

fi

else

echo "user $1 doesn&#39;t exits"

fi

练习5:通过命令行参数给定两个两个文件名,如果某文件不存在,则结束脚本执行,如果都存在时返回两个文件的行数之和

#!/bin/bash

#如果没有传递参数,直接退出

if [ $# -lt 2 ];then

echo "please send two argument"

exit 1

fi

if [ -e $1 -a -e $2 ];then #(-e exist 表示存在, -a and)

totalLines=$[ $(grep ".*" $1 |wc -l)+$(grep ".*" $2 |wc -l) ]

echo "The total lines are $totalLines"

else

echo "The file doesn&#39;t exists"

exit 1

fi

二,read命令:通过键盘输入数据,将键盘输入的值传递给脚本的中定义的变量,从而完成变量赋值操作 。脚本中使用read命令可以使得用户能够与程序进行交互

read [选项] [变量名]

这里变量名的意义在于将用户输入的值传递给这个变量名,那么在脚本中我们就可以拿到用户输入的值了

选项:

-p (promp):在用户在键盘输入数据时,指定显示提示符

-t(timeout):指定超时时间,如果用户在指定的超时时间都没有输入的话,那么就终止脚本的执行

练习:通过脚本创建一个用户,并设置密码,要求:需要用户交互式输入用户名和密码,如果用户名存在,终止脚本,如果不存在就创建,且设置密码

#!/bin/bash

read -p "Enter a user name:" name #在屏幕上显示提示语句“Enter a user name:”

[ -z "$name" ] && echo "a user name is needed." && exit 1 #-z表示输入的字符串 $name 为空

if id $name &>/dev/null ;then #检测用户是否存在

echo "$name already exists."

exit 2

else #用户不存在,则创建此用户,并设置密码

read -p "Enter a passwd for $name,defaults is &#39;password&#39;:" password

[ -z "$password" ] && password="password" #将空密码或者输入的不为空的密码传递给密码

adduser $name

echo "$password" | password --stdin $name &>/dev/null #将密码赋给此用户并不在屏幕输出

echo "Add user $name"

fi

(1)在运行脚本前,我们一般先对脚本的语法进行检查,如果脚本有bug,我们再调试脚本

语法检查 bash -n 脚本路径

脚本调试 bash -x 脚本路径

(2)过程式编程语言的执行流程 执行顺序 选择顺序 循环顺序

选择执行

(1)&&,||

command1 && command2:如果command1正确,也执行command2;如果command1不正确,不执行command2

command1 || command2:如果command1正确,不执行command2;如果command1不正确,执行command2

(2)if语句

(3)case语句

if嵌套语句格式

if [ 条件 ];then

if [ 条件 ];then

执行这里的代码

fi

fi

if [ 条件 ];then

if [ 条件 ];then

执行这里的代码

fi

else

if [ 条件 ];then

执行这里的代码

fi

fi

if 多分支语句格式(注意:多个分支只会执行一个,执行首先为真的分支)

if [ 条件1 ];then

条件1为真执行这里的代码

elif [ 条件2 ];then

条件2为真执行这里的代码

elif [ 条件3 ];then

条件3为真执行这里的代码

.

.

.

elif [ 条件n ];then

条件n为真执行这里的代码

else

如果所有的条件都不满足时,执行这里的代码

fi

示例1:通过脚本参数传递一个文件路径给脚本,判断此文件的类型

#!/bin/bash

if [ $# -lt 1 ];then

echo "A argument is needed."

exit 1

fi

if ! [ -e $1 ];then

echo "No such file or directory."

exit 2

fi

if [ -f $1 ];then

echo "Common file"

elif [ -d $1 ];then

echo "Directory file"

elif [ -L $1 ];then

echo "Symbolic link"

elif [ -b $1 ];then

echo "block file"

elif [ -c $1 ];then

echo "character special file"

elif [ -S $1 ];then

echo "Socket file"

else

echo "Unknow"

fi

示例2,传递一个参数给脚本,此参数为用户名根据其ID号来判断用户类型:0:管理员 ,1-499:系统用户,500+:为登入用户, 输出用户是那种类型的用户

#!/bin/bash

if [ $# -lt 1 ];then

echo "A argument is needed."

exit 1

fi

if id -u $1 &>/dev/null;then

userid=$(id -u $1)

if [ $userid -eq 0 ];then

echo "Administrator"

elif [ $userid -ge 1 -a $userid -le 499 ];then

echo "System user"

elif [ $userid -ge 500 ];then

echo "Login user"

fi

else

echo "No such user."

fi

示例3,1)列出如下菜单给用户disk) show disks infomem)show memory infocpu)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 "Please input your option:" option

option=$(echo $option | tr [A-Z] [a-z]) #将输入的大写转换成小写

if [ $option == "disk" ];then

fdisk -l

elif [ $option == "mem" ];then

free -m

elif [ $option == "cpu" ];then

lscpu

elif [ $option == "*" ];then

exit 1

else

echo "Wrong option"

fi

循环就是将一段代码重复执行0,1次或多次。

进入条件:条件满足时,需要进入循环 , 退出条件:每个循环都应该有退出条件,有机会退出循环

bash的循环分类: for循环,while循环,until循环

for循环有两种格式 (重点)

第一种格式:遍历列表 (重点)

第二种格式:控制变量 (重点)

变量列表

for 变量 in 列表; do

循环体

done

进入条件:只要列表中有元素,即可进入循环 ; 退出循环:列表中的元素遍历完成

示例

#!/bin/bash

for username in user1 user2 user3;do

if id $username &>/dev/null;then

echo "$username is already exists."

else

useradd $username

echo "Add &username success"

fi

done

列表生成的方式

(1)直接取出

例如: user1 user2 user3

(2)整数列表

例如 {1..100}

例如 `seq 1 2 100` 注意:中间的2表示步长

(3)返回列表的命令

`ls /var/log/`

(4)glob

例如: /var/log/*

(5)变量引用,如:@* ,

示例1:求100内所有正整数之和

#!/bin/bash

# 求100内所有正整数之和

# 申明sum为正整数

declare -i sum=0

for i in {1..100}; do

sum=$[ $sum+$i ]

done

echo "$sum"

示例2:列出/var/log/目录下所有文件的类型

#!/bin/bash

# 列出/var/log/目录下所有文件的类型

for option in /var/log/*; do

if [ -f $option ];then

echo "$option is Common file"

elif [ -d $option ];then

echo "$option is Directory"

elif [ -L $option ];then

echo "$option is Symbolic link"

elif [ -b $option ];then

echo "$option is block special file"

elif [ -c $option ];then

echo "$option is character special file"

elif [ -S $option ];then

echo "$option is Socket file"

else

echo "Unknow"

fi

done

练习1:分别求100以内所有偶数之和,奇数之和

#!/bin/bash

# 1:分别求100以内所有偶数之和,奇数之和

declare -i oven=0

declare -i odd=0

for i in {1..100}; do

count=$[ $i % 2 ]

if [[ $count == 0 ]]; then

oven=$[ $oven + $i ]

else

odd=$[ $odd + $i ]

fi

done

echo "oven is $oven"

echo "odd is $odd"

相关文章
最新文章
热点推荐