shell

shell.2.0 bash编程基础(条件测试、组合条件测试、位置变量、特殊变量、if单双分支)

 

关键词:条件测试、条件测试类型、组合条件测试、向脚本传递参数、位置变量、特殊变量、选择执行语句(if单分支与双分支);

1、bash shell 脚本通用格式

[root@localhost tmp]# more first.sh 
#!/bin/bash
# descriptions:
# version:V1.0
# author:Fitz<fitz@kouyuushinn.cn>
# date:2018-05-05
[root@localhost tmp]#

NOTE: 在脚本中的各个应用段落中必须添加脚本注释,说明此段脚本的功用;

2、条件测试
判断某需求是否满足,需要由测试机制来实现;

测试表达式的方式
>>   执行命令,并利用命令状态返回值来判断;
0         :    表示成功;
1-255 : 表示失败;

>> 测试表达式
test     EXPRESSION
[ EXPRESSION ]
[[ EXPRESSION ]]

3、bash的测试类型

3.1 数值测试(双目测试类型)
-eq : 是否等于; [ $num1 -eq $num2 ] , 注意中括号内部前后2端都是有空格的;
-ne : 是否不等于;
-gt : 是否大于;
-ge : 是否大于等于;
-lt : 是否小于;
-le : 是否小于等于;

3.2 字符串测试(双目测试类型)
== : 是否等于;
> : 是否大于;
< : 是否小于;
!= : 是否不等于;
=~ : 左侧字符串是否能够被右侧的PATTERN所匹配;做部分匹配;

单目测试类型:
-z    “STRING” :   判断指定的字符串是否为空,空则为真,不空则为假;
-n    “STRING” :   判断指定的字符串是否为不空,不空则为真,空则为假;

字符串测试注意事项:
字符串需要用引号;
单纯的字符串比较时,使用双中括号;[[ “STRING1” == “STRING2” ]];
带条件判断的语句时,使用单中括号;[ EXPRESSION == EXPRESSION ]; 此种情况的举例在”组合条件测试”中;

脚本的状态返回值,默认是脚本中执行的最后一条命令的状态返回值;
在脚本中可自定义状态码,exit [n] : 数字n为自定义的;
shell进程遇到”exit”时,进程即会终止;

3.3 文件测试(单目测试类型)

>> 存在性测试
-a   FILE :  文件的存在性测试,存在则为真,否则为假;
-e   FILE :  文件的存在性测试,存在则为真,否则为假;

>> 存在性及类型测试
-b   FILE :  是否存在并且为 块设备 文件;如果存在且为 块设备 文件,则为真,否则(如果存在,但不是块设备文件)为假;真假判断,下面相同;
-c   FILE :  是否存在并且为 字符设备 文件;
-d   FILE :  是否存在并且为 目录 文件;
-f   FILE :  是否存在并且为 普通文件;
-h   FILE 或 -L   FILE :  是否存在并且为 符号链接文件;
-p   FILE :  是否存在并且为 管道文件;
-S   FILE :  是否存在并且为 套接字文件;注意,是大写字母”S”;

>> 存在性及文件权限测试
-r   FILE :  是否存在并且对当前用户可读;如果存在并且对当前用户可读,则为真,否则(如果存在,但对当前用户的权限不可读)为假;
-w  FILE :  是否存在并且对当前用户可写;
-x   FILE :  是否存在并且对当前用户可执行;

>> 特殊权限测试
-u  FILE :  是否存在并且 拥有suid权限;存在且有suid权限,则为真;存在,但没有suid权限,则为假;
-g  FILE :  是否存在并且 拥有sgid权限;
-k  FILE :  是否存在并且 拥有sticky权限;

>>从属关系测试
-O  FILE :  是否存在,并且,当前用户是否为文件的属主;存在,且当前用户是文件的属主,则为真;存在,但当前用户不是文件的属主,则为假;
-G  FILE :  是否存在,并且,当前用户是否属于文件的属组;

>> 时间戳测试
-N   FILE : 文件是否存在,并且自上一次读操作后是否被修改过;存在,且自上一次读操作后修改过,则为真;存在,但自上次读操作后未做修改,则为假;

>> 文件是否有内容测试
-s   FILE :  文件存在并且是否有内容;存在且有内容,则为真;存在但无内容,则为假;

>> 双目测试
FILE1   -ef   FILE2 :     FILE1与FILE2是否指向同一个文件系统的相同的inode的硬链接;
FILE1   -nt   FILE2 :    FILE1是否新于FILE2;
FILE1   -ot   FILE2 :    FILE1是否旧于FILE2;

4、组合条件测试

逻辑运算的组合条件测试,第一种方式
COMMOND1   &&   COMMOND2        与运算
COMMOND1    ||     COMMOND2        或运算
!COMMOND

逻辑运算的组合条件测试,第二种方式
EXPRESSION1    -a    EXPRESSION2
EXPRESSION1    -o    EXPRESSION2
!EXPRESSION

举例:组合条件测试
将当前主机名称保存至hostName变量中;主机名如果为空,或者为localhost.localdomain,或者为localhost,则将主机名设置为kouyuushinn.cn;

[root@localhost tmp]# hostName="$HOSTNAME"
[root@localhost tmp]# 
[root@localhost tmp]# [ -z "$hostName" -o "$hostName" == "localhost.localdomain" -o "$hostName" == "localhost" ] && hostnamectl set-hostname kouyuushinn.cn
[root@localhost tmp]# hostname
kouyuushinn.cn
[root@localhost tmp]#

5、向脚本传递参数

变量有5种类型
本地变量 : 作用域仅为当前shell进程;
环境变量 : 作用域为当前shell进程及其子进程;
局部变量 : 作用域仅为某代码片段(函数上下文);
位置参数变量 : 向执行脚本的shell进程传递的参数;
特殊变量 : shell内置的有特殊功用的变量;

5.1 位置参数变量的变量引用方式
$1 : 表示脚本中传递的第一个参数变量;
$2 : 表示脚本中传递的第二个参数变量;
$3 : 依次类推;

传递的参数变量的轮替
shift [n] : 位置参数轮替,默认踢掉第一个参数变量,可指定数字,表示踢掉前面”n”个参数变量;

举例1:
传递2个参数变量给脚本,参数变量是2个文件,计算2个文件的空白行的行数之和;

#!/bin/bash
#
count_file1=$(grep "^[[:space:]]*$" $1 | wc -l)
shift
count_file2=$(grep "^[[:space:]]*$" $1 | wc -l)

count_file_sum=$[$count_file1+$count_file2]

echo "coung_file_sum is: $count_file_sum."

5.2 特殊变量
$0 : 脚本文件路径本身;
$# : 脚本参数的个数(数量);

$* : 列出脚本的所有参数,各个参数是独立的字符串;
$@ : 列出脚本的所有参数,所有参数做为一个字符串;

举例2:

#!/bin/bash
#
[ $# -lt 2 ] && echo "arg is requit two files." && exit 11

count_file1=$(grep "^[[:space:]]*$" $1 | wc -l)
shift
count_file2=$(grep "^[[:space:]]*$" $1 | wc -l)

count_file_sum=$[$count_file1+$count_file2]

echo "coung_file_sum is: $count_file_sum."

6、过程式编程语言的代码执行顺序的类型
顺序执行:代码逐条执行;
选择执行:代码只有一个分支,条件满足时才会执行;代码有2个或以上分支,只会执行其中一个满足条件的分支;
循环执行:代码片段(循环体)要执行0、1或多个来回;

7、选择执行
>> 单分支if语句
if    测试条件;then
      代码分支
fi

双分支if语句
if    测试条件;then
      条件为真时执行的分支
else
      条件为假时执行的分支
fi     

[root@kouyuushinn tmp]# 
[root@kouyuushinn tmp]# more third.sh 
#!/bin/bash
#
if [ $# -lt 1 ];then
  echo "at least one username."
  exit 11
elif [ $# -ge 2 ];then
  echo "requit only one username."
  exit 22
elif ! grep "^$1\>" /etc/passwd &> /dev/null;then
  useradd $1
  echo "$1" | passwd --stdin $1 &> /dev/null
  echo "add user $1 is finished. user $1 password is $1." 
else
  echo "$1 is already exits."
fi
[root@kouyuushinn tmp]# 
[root@kouyuushinn tmp]# ./third.sh 
at least one username.
[root@kouyuushinn tmp]# 
[root@kouyuushinn tmp]# ./third.sh user01 user02
requit only one username.
[root@kouyuushinn tmp]# 
[root@kouyuushinn tmp]# ./third.sh user01
add user user01 is finished. user user01 password is user01.
[root@kouyuushinn tmp]#

 

举例,通过命令行参数给定2个数字,输出其中较大的数值;

脚本1:只判断了参数个数,未对参数是否整数进行判断;
#!/bin/bash
#
if [ $# -lt 2 -o $# -gt 2 ];then
  echo "need two integers."
  exit 22
fi

if [ $1 -ge $2 ];then
  echo "max num is $1."
else
  echo "max num is $2."
fi

脚本2:只判断了参数个数,未对参数是否整数进行判断;
#!/bin/bash
#
declare -i max=$1

if [ $# -lt 2 -o $# -gt 2 ];then
  echo "need two integers."
  exit 22
fi

if [ $1 -lt $2 ];then
  max=$2
fi

echo "max num is $max."

通过命令行参数给定1个用户名,判断其ID号是偶数还是奇数;
先判断参数个数;
再判断参数(用户)是否存在,如果存在,则输出UID号,对此UID号进行取模运算,判断是偶数还是奇数;
如果判断用户不存在,则创建用户,取出UID号,并对此UID号进行取模运算,判断是偶数还是奇数;

#!/bin/bash
#
if [ $# -lt 1 -o $# -gt 1 ];then
  echo
  echo "need one arg."
  exit 11
fi

id $1 &> /dev/null

if [ $? -eq 0 ];then
  echo
  echo "user $1 is already exits.it's UID : `id -u $1`."
else 
  echo
  echo "user $1 is not exits.create user $1 now..."
  useradd $1 &> /dev/null
  echo "$1" | passwd --stdin $1 &> /dev/null
  echo 
  echo "add user $1 is finishied."
  echo
  echo "user $1 UID is `id -u $1`."
fi

auid=`id -u $1`

if [ $[$auid%2] -eq 0 ];then
  echo
  echo "$1 UID is even number."
else 
  echo "$1 UID is odd number."
fi

通过命令行参数给定2个文本文件名,返回每个文件的行数,并说明其中行数较多的文件;

#!/bin/bash
#
if [ $# -lt 2 -o $# -gt 2 ];then
  echo
  echo "Just need two args."
  exit 22
  echo "exit 22"
fi

if [ ! -f $1 -o ! -f $2 ];then
  echo
  echo "Need two files,not the other filesystem."
  exit 33
  echo "exit 33."
fi

file1_line=`cat $1 | wc -l`
echo "$1 file lines are $file1_line."
file2_line=`cat $2 | wc -l`
echo
echo "$2 file lines are $file2_line." 

if [ $file1_line -ge $file2_line ];then
  echo
  echo "The lager file's line is $1."
else
  echo
  echo "The lager file's line is $2."
fi

 

Leave a Reply

Your email address will not be published. Required fields are marked *