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

条件测试语法有两种书写模式,一种是[ 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'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'IDNum is $idNum and oven"
   else
      echo "$1'IDNum is $idNum and odd"
   fi
else
    echo "user $1 doesn'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'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 'password':" 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"    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值