21.第六章 Shell脚本编程基础入门(四)

2.11 条件测试命令

条件测试:判断某需求是否满足,需要由测试机制来实现,专用的测试表达式需要由测试命令辅助完成测试过程,实现评估布尔声明,以便用在条件性环境下进行执行

若真,则状态码变量 $? 返回0

若假,则状态码变量 $? 返回1

条件测试命令

  • test EXPRESSION
  • [ EXPRESSION ] #和test 等价,建议使用 [ ]
  • [[ EXPRESSION ]] 相当于增强版的test, 且支持正则表达式和通配符

注意:EXPRESSION前后必须有空白字符

范例:

[root@rocky8 bin]# type test
test is a shell builtin
[root@rocky8 bin]# help type
type: type [-afptP] name [name ...]
    Display information about command type.
    
    For each NAME, indicate how it would be interpreted if used as a
    command name.
    
    Options:
      -a	display all locations containing an executable named NAME;
    		includes aliases, builtins, and functions, if and only if
    		the `-p' option is not also used
      -f	suppress shell function lookup
      -P	force a PATH search for each NAME, even if it is an alias,
    		builtin, or function, and returns the name of the disk file
    		that would be executed
      -p	returns either the name of the disk file that would be executed,
    		or nothing if `type -t NAME' would not return `file'
      -t	output a single word which is one of `alias', `keyword',
    		`function', `builtin', `file' or `', if NAME is an alias,
    		shell reserved word, shell function, shell builtin, disk file,
    		or not found, respectively
    
    Arguments:
      NAME	Command name to be interpreted.
    
    Exit Status:
    Returns success if all of the NAMEs are found; fails if any are not found.


[root@rocky8 bin]# test -z ""
[root@rocky8 bin]# echo $?
0
#test -z ""	 -z 是只要为空就是真

[root@rocky8 bin]# test -z "abc"
[root@rocky8 bin]# echo $?
1
#非空 就是假

[root@rocky8 bin]# test -z " "
[root@rocky8 bin]# echo $?
1
#如果里边是空格,空格在ASCII表里代表字符,它在磁盘上是占空间的,也是假

[root@rocky8 bin]# echo " " >a.txt
[root@rocky8 bin]# ll a.txt 
-rw-r--r-- 1 root root 2 Oct  9 18:02 a.txt #空格占2个字节
[root@rocky8 bin]# hexdump -C a.txt 
00000000  20 0a                                             | .|
00000002
#20 就代表空格

[root@rocky8 bin]# name=raymond
[root@rocky8 bin]# test -z "$name"
[root@rocky8 bin]# echo $?
1
[root@rocky8 bin]# unset name
[root@rocky8 bin]# test -z "$name"
[root@rocky8 bin]# echo $?
0

#test -n  与test -z 正好相反

[root@rocky8 bin]# str1=abc
[root@rocky8 bin]# str2=def
[root@rocky8 bin]# test $str1 = $str2
[root@rocky8 bin]# echo $?
1

[root@rocky8 bin]# str2=abc
[root@rocky8 bin]# test $str1 = $str2
[root@rocky8 bin]# echo $?
0
#两个字符串相同为真,不同为假


[root@rocky8 bin]# type [
[ is a shell builtin
[root@rocky8 bin]# help [
[: [ arg... ]
    Evaluate conditional expression.
    
    This is a synonym for the "test" builtin, but the last argument must
    be a literal `]', to match the opening `['.
#[] 中括号和test是等价的

[root@rocky8 bin]# [ $str1 = $str2 ]
[root@rocky8 bin]# echo $?
0
#注意中括号的两边都要加空格

[root@rocky8 bin]# [ $str1 = $str2]
-bash: [: missing `]'
[root@rocky8 bin]# [$str1 = $str2 ]
-bash: [abc: command not found
[root@rocky8 bin]# [ $str1 = $str2 ]
[root@rocky8 bin]# echo $?
0

二进制 0 假  1 真
$?  是十进制  0 真   1-255 假

!=   叹号等于号  是字符串中表示不等于

-eq 等于, -ne  不等于,-lt  小于, -le 小于等于, -gt 大于 ,  -ge 大于等于.

[root@rocky8 bin]# [ 10 -lt 20 ] #10 小于20
[root@rocky8 bin]# echo $?
0
[root@rocky8 bin]# [ 10 -gt 20 ] #10 大于20
[root@rocky8 bin]# echo $?
1

[root@rocky8 bin]# i=2
[root@rocky8 bin]# j=3
[root@rocky8 bin]# [ $i -eq $j ] #$i 等于$j
[root@rocky8 bin]# echo $?
1

[root@rocky8 bin]# ls cmd;[ $? -eq 0 ]
ls: cannot access 'cmd': No such file or directory
[root@rocky8 bin]# echo $?
1
#判断命令执行结果是否成功

[root@rocky8 bin]# ll /etc/issue
-rw-r--r--. 1 root root 23 Jun 19 22:22 /etc/issue
[root@rocky8 bin]# [ -w /etc/issue ]
[root@rocky8 bin]# echo $?
0
#判断文件是否可写

[root@rocky8 bin]# ll /etc/shadow
---------- 1 root root 840 Oct  8 18:33 /etc/shadow
[root@rocky8 bin]# [ -w /etc/shadow ]
[root@rocky8 bin]# echo $?
0
#root是有写权限的

[root@rocky8 bin]# [ -x /etc/shadow ]
[root@rocky8 bin]# echo $?
1
#不管是谁,没有执行权限,都没有执行权限

[root@rocky8 bin]# [ -a /etc/shadow ]
[root@rocky8 bin]# echo $?
0
#判断是否存在

[root@rocky8 bin]#  [ ! -a /etc/shadow ]
[root@rocky8 bin]# echo $?
0
#-a 加!,是不行的
[root@rocky8 bin]# [ ! -e /etc/shadow ]
[root@rocky8 bin]# echo $?
1
#! -e  才能判断是否不存在

2.11.1 变量测试

#判断 NAME 变量是否定义
[ -v NAME ]

#判断 NAME 变量是否定义并且是名称引用,bash 4.4新特性
[ -R NAME ]

范例:

[root@rocky8 bin]# unset x
[root@rocky8 bin]# test -v x
[root@rocky8 bin]# echo $?
1
[root@rocky8 bin]# x=10
[root@rocky8 bin]# test -v x
[root@rocky8 bin]# echo $?
0
[root@rocky8 bin]# y=
[root@rocky8 bin]# test -v y
[root@rocky8 bin]# echo $?
0

#注意 [ ] 需要空格,否则会报下面错误
[root@rocky8 bin]# [-v y]
-bash: [-v: command not found

[root@rocky8 bin]# [ -v y ]
[root@rocky8 bin]# echo $?
0

2.11.2 数值测试

-eq 是否等于
-ne 是否不等于
-gt 是否大于
-ge 是否大于等于
-lt 是否小于
-le 是否小于等于

范例:

[root@rocky8 bin]# i=10
[root@rocky8 bin]# j=8
[root@rocky8 bin]# [ $i -lt $j ]
[root@rocky8 bin]# echo $?
1

[root@rocky8 bin]# [ $i -gt $j ]
[root@rocky8 bin]# echo $?
0
[root@rocky8 bin]# [ i -gt j ]
-bash: [: i: integer expression expected

算术表达式比较

<=
>=
<
>

范例:

[root@rocky8 bin]# x=10;y=20;(( x > y ));echo $?
1
[root@rocky8 bin]# x=10;y=20;(( x < y ));echo $?
0

2.11.3 字符串测试

test和 [ ]用法

test和 [ ]用法
-z STRING 字符串是否为空,没定义或空为真,不空为假,
-n STRING 字符串是否不空,不空为真,空为假
   STRING 同上

STRING1 = STRING2 是否等于,注意 = 前后有空格
STRING1 != STRING2 是否不等于
> ascii码是否大于ascii码
< 是否小于

[[]] 用法

[[ expression ]] 用法
== 左侧字符串是否和右侧的PATTERN相同
    注意:此表达式用于[[ ]]中,PATTERN为通配符
=~ 左侧字符串是否能够被右侧的正则表达式的PATTERN所匹配
    注意: 此表达式用于[[ ]]中;扩展的正则表达式

建议:当使用正则表达式或通配符使用[[ ]],其它情况一般使用 [ ]

范例:使用 [ ]

[root@rocky8 bin]# unset str
[root@rocky8 bin]# [ -z "$str" ]
[root@rocky8 bin]# echo $?
0
[root@rocky8 bin]# str=""
[root@rocky8 bin]# [ -z "$str" ]
[root@rocky8 bin]# echo $?
0
[root@rocky8 bin]# str=" "
[root@rocky8 bin]# [ -z "$str" ]
[root@rocky8 bin]# echo $?
1
[root@rocky8 bin]# [ -n "$str" ]
[root@rocky8 bin]# echo $?
0

[root@rocky8 bin]# unset str
[root@rocky8 bin]# [ -n "$str" ]
[root@rocky8 bin]# echo $?
1
[root@rocky8 bin]# [ "$str" ]
[root@rocky8 bin]# echo $?
1

[root@rocky8 bin]# str="raymond"
[root@rocky8 bin]# [ "$str" ]
[root@rocky8 bin]# echo $?
0

[root@rocky8 bin]# str1="raymond"
[root@rocky8 bin]# str2="boss"
[root@rocky8 bin]# [ $str1 = $str2 ]
[root@rocky8 bin]# echo $?
1
[root@rocky8 bin]# str2="raymond"
[root@rocky8 bin]# [ $str1 = $str2 ]
[root@rocky8 bin]# echo $?
0

范例:在比较字符串时,建议变量放在“ ”中

[root@rocky8 bin]# NAME="I love linux"
[root@rocky8 bin]# [ $NAME ]
-bash: [: love: binary operator expected
[root@rocky8 bin]# [ "$NAME" ]
[root@rocky8 bin]# echo $?
0
[root@rocky8 bin]# [ I love linux ]
-bash: [: love: binary operator expected

范例:使用 [[ ]]

#通配符
[root@rocky8 bin]# FILE=test.log
[root@rocky8 bin]# [[ "$FILE" == *.log ]]
[root@rocky8 bin]# echo $?
0
[root@rocky8 bin]# FILE=test.txt
[root@rocky8 bin]# [[ "$FILE" == *.log ]]
[root@rocky8 bin]# echo $?
1
[root@rocky8 bin]# [[ "$FILE" != *.log ]]
[root@rocky8 bin]# echo $?
0

#正则表达式
[root@rocky8 bin]# [[ "$FILE" =~ \.log$ ]]
[root@rocky8 bin]# echo $?
1
[root@rocky8 bin]# FILE=test.log
[root@rocky8 bin]# [[ "$FILE" =~ \.log$ ]]
[root@rocky8 bin]# echo $?
0

[root@rocky8 bin]# N=100
[root@rocky8 bin]# [[ "$N" =~ ^[0-9]+$ ]]
[root@rocky8 bin]# echo $?
0
[root@rocky8 bin]# N=Raymond10
[root@rocky8 bin]# [[ "$N" =~ ^[0-9]+$ ]]
[root@rocky8 bin]# echo $?
1

[root@rocky8 bin]# IP=1.2.3.4
[root@rocky8 bin]# [[ "$IP" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]
[root@rocky8 bin]# echo $?
0
[root@rocky8 bin]# IP=1.2.3.4567
[root@rocky8 bin]# [[ "$IP" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]
[root@rocky8 bin]# echo $?
1

[root@rocky8 bin]# [[ $IP =~ ^(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$ ]]
[root@rocky8 bin]# echo $?
1

#通配符
[root@rocky8 bin]# NAME="linux1"
[root@rocky8 bin]# [[ "$NAME" == linux* ]]
[root@rocky8 bin]# echo $?
0
[root@rocky8 bin]# [[ "$NAME" == "linux*" ]]
[root@rocky8 bin]# echo $?
1
[root@rocky8 bin]# NAME="linux*"
[root@rocky8 bin]# [[ "$NAME" == "linux*" ]]
[root@rocky8 bin]# echo $?
0

#结论:[[ == ]] == 右侧的 * 做为通配符,不要加“”,只想做为*, 需要加“” 或转义

2.11.4 文件测试

存在性测试

-a FILE:同 -e
-e FILE: 文件存在性测试,存在为真,否则为假
-b FILE:是否存在且为块设备文件
-c FILE:是否存在且为字符设备文件
-d FILE:是否存在且为目录文件
-f FILE:是否存在且为普通文件
-h FILE 或 -L FILE:存在且为符号链接文件
-p FILE:是否存在且为命名管道文件
-S FILE:是否存在且为套接字文件

范例:

[root@rocky8 bin]# [ -a /etc/nologin ]
[root@rocky8 bin]# echo $?
1
[root@rocky8 bin]# ! [ -a /etc/nologin ]
[root@rocky8 bin]# echo $?
0

[root@rocky8 bin]# [ -d /etc ]
[root@rocky8 bin]# echo $?
0
[root@rocky8 bin]# [ -d /etc/issue ]
[root@rocky8 bin]# echo $?
1

[root@rocky8 bin]# [ -L /bin ]
[root@rocky8 bin]# echo $?
0
[root@rocky8 bin]# [ -L /bin/ ]
[root@rocky8 bin]# echo $?
1

文件权限测试:

-r FILE:是否存在且可读
-w FILE: 是否存在且可写
-x FILE: 是否存在且可执行
-u FILE:是否存在且拥有suid权限
-g FILE:是否存在且拥有sgid权限
-k FILE:是否存在且拥有sticky权限

注意:最终结果由用户对文件的实际权限决定,而非文件属性决定

范例:

[root@rocky8 bin]# [ -w /etc/shadow ]
[root@rocky8 bin]# echo $?
0
[root@rocky8 bin]# [ -x /etc/shadow ]
[root@rocky8 bin]# echo $?
1

[root@rocky8 bin]# touch test.txt
[root@rocky8 bin]# [ -w test.txt ]
[root@rocky8 bin]# echo $?
0
[root@rocky8 bin]# chattr +i test.txt
[root@rocky8 bin]# lsattr test.txt
----i--------------- test.txt
[root@rocky8 bin]# [ -w test.txt ]
[root@rocky8 bin]# echo $?
1
[root@rocky8 bin]# chattr -i test.txt
[root@rocky8 bin]# [ -w test.txt ]
[root@rocky8 bin]# echo $?
0

文件属性测试

-s FILE #是否存在且非空
-t fd #fd 文件描述符是否在某终端已经打开
-N FILE #文件自从上一次被读取之后是否被修改过
-O FILE #当前有效用户是否为文件属主
-G FILE #当前有效用户是否为文件属组
FILE1 -ef FILE2 #FILE1是否是FILE2的硬链接
FILE1 -nt FILE2 #FILE1是否新于FILE2(mtime)
FILE1 -ot FILE2 #FILE1是否旧于FILE2

2.12 关于 () 和 {}

(CMD1;CMD2;…)和 { CMD1;CMD2;…; } 都可以将多个命令组合在一起,批量执行

[root@rocky8 bin]# man bash
       (list) list  is executed in a subshell environment (see COMMAND EXECUTION ENVIRONMENT below).  Variable assignments and builtin com‐
              mands that affect the shell's environment do not remain in effect after the command completes.  The return status is the exit
              status of list.

       { list; }
              list  is  simply  executed  in  the current shell environment.  list must be terminated with a newline or semicolon.  This is
              known as a group command.  The return status is the exit status of list.  Note that unlike the metacharacters ( and ), {  and
              }  are  reserved  words  and  must occur where a reserved word is permitted to be recognized.  Since they do not cause a word
              break, they must be separated from list by whitespace or another shell metacharacter.
( list ) 会开启子shell,并且list中变量赋值及内部命令执行后,将不再影响后续的环境,
帮助参看:man bash 搜索(list)

{ list; } 不会启子shell, 在当前shell中运行,会影响当前shell环境
帮助参看:man bash 搜索{ list; }

范例:

[root@rocky8 bin]# (ls;pwd)
arg.sh  a.txt  backup.sh  chook_rabbit.sh  f1.sh  f2.sh  file.sh  link_test2.sh  link_test3.sh  link_test.sh  rm.sh  set2.sh  set.sh  test.txt
/root/bin
[root@rocky8 bin]# { ls;pwd; }
arg.sh  a.txt  backup.sh  chook_rabbit.sh  f1.sh  f2.sh  file.sh  link_test2.sh  link_test3.sh  link_test.sh  rm.sh  set2.sh  set.sh  test.txt
/root/bin

[root@rocky8 bin]# { ls;pwd } #后边的;分号不能少
> ^C

[root@rocky8 bin]# echo $BASHPID
2160
[root@rocky8 bin]#  { echo $BASHPID;sleep 100; }
2160
[root@rocky8 ~]# pstree -p |grep bash
           |-sshd(756)-+-sshd(2147)---sshd(2159)---bash(2160)---sleep(2284)
           |           `-sshd(2285)---sshd(2287)---bash(2288)-+-grep(2312)
#{} 花括号是在当前shell环境中执行的,不会开启子shell

[root@rocky8 bin]#  ( echo $BASHPID;sleep 100 )
2313
[root@rocky8 ~]# pstree -p |grep bash
           |-sshd(756)-+-sshd(2147)---sshd(2159)---bash(2160)---bash(2313)---sleep(2314)
           |           `-sshd(2285)---sshd(2287)---bash(2288)-+-grep(2316)
#() 执行在子shell中

[root@rocky8 bin]# ( umask 123;touch 123.txt );touch 234.txt
[root@rocky8 bin]# ll *.txt
-rw-r--r-- 1 root root 0 Oct  9 19:23 123.txt
-rw-r--r-- 1 root root 0 Oct  9 19:23 234.txt
#666-123=543,奇数位加1,644
[root@rocky8 bin]# umask
0022
#666-022=644

[root@rocky8 bin]# ( umask 345;touch 123.txt );touch 234.txt; ll *.txt
-rw-r--r-- 1 root root 0 Oct  9 19:24 123.txt
-rw-r--r-- 1 root root 0 Oct  9 19:24 234.txt
#() 小括号 会开启子shell,只在子shell中有效,退出之后,它就不影响原来的umask

[root@rocky8 bin]# { umask 345;touch 123.txt; };touch 234.txt;ll *.txt
-rw-r--r-- 1 root root 0 Oct  9 19:24 123.txt
-rw-r--r-- 1 root root 0 Oct  9 19:24 234.txt

范例: () 和 {}

[root@rocky8 bin]# name=boss;(echo $name;name=raymond;echo $name;);echo $name
boss
raymond
boss

[root@rocky8 bin]# name=boss;{ echo $name;name=raymond;echo $name; };echo $name
boss
raymond
raymond

[root@rocky8 ~]# umask
0022
[root@rocky8 ~]# (umask 066;touch f1.txt)
[root@rocky8 ~]# ll f1.txt
-rw------- 1 root root 0 Oct  9 19:28 f1.txt
[root@rocky8 ~]# umask
0022

[root@rocky8 ~]# ( cd /data;ls )
app.conf  systeminfo.sh  test.sh  test.txt
[root@rocky8 ~]# pwd
/root
[root@rocky8 ~]# { cd /data;ls; }
app.conf  systeminfo.sh  test.sh  test.txt
[root@rocky8 data]# pwd
/data

#()会开启子shell
[root@rocky8 data]# echo $BASHPID
2340
[root@rocky8 data]# ( echo $BASHPID;sleep 100)
2370
[root@rocky8 ~]# pstree -p |grep bash
           |-sshd(756)-+-sshd(2285)---sshd(2287)---bash(2288)-+-grep(2373)
           |           `-sshd(2337)---sshd(2339)---bash(2340)---bash(2370)---sleep(2371)

#{ } 不会开启子shell
[root@rocky8 data]# echo $BASHPID
2340
[root@rocky8 data]# { echo $BASHPID; }
2340

2.13 组合测试条件

2.13.1 第一种方式 [ ]

[ EXPRESSION1 -a EXPRESSION2 ] 并且,EXPRESSION1和EXPRESSION2都是真,结果才为真
[ EXPRESSION1 -o EXPRESSION2 ] 或者,EXPRESSION1和EXPRESSION2只要有一个真,结果就为真
[ ! EXPRESSION ] 取反

说明: -a 和 -o 需要使用测试命令进行,[[ ]] 不支持

范例:

[root@rocky8 data]# FILE=/etc/issue ;[ -f $FILE -a -x $FILE ]
[root@rocky8 data]# echo $?
1

[root@rocky8 data]# ll /etc/issue
-rw-r--r--. 1 root root 23 Jun 19 22:22 /etc/issue
[root@rocky8 data]#  ll /bin/ls
-rwxr-xr-x. 1 root root 143408 Mar 15  2021 /bin/ls
[root@rocky8 data]# FILE=/bin/ls;[ -f $FILE -a -x $FILE ]
[root@rocky8 data]# echo $?
0
#-a 与两个条件都为真,才是真

[root@rocky8 data]# FILE=/etc/issue ;[ -f $FILE -o -x $FILE ]
[root@rocky8 data]# echo $?
0
#-o 或两个添加中有一个为真,就是真

[root@rocky8 data]# FILE=/etc/issue;[ ! -x $FILE ]
[root@rocky8 data]# echo $?
0
[root@rocky8 data]# FILE=/etc/issue;! [ -x $FILE ]
[root@rocky8 data]# echo $?
0
# ! 取反 ,可以放在中括号里边,也可以放在外边,一般都是放在里边

范例:

[root@centos8 ~]#ll /data/scrips/test.sh
-rw-r--r-- 1 root root 382 Dec 23 09:32 /data/scripts/test.sh
[root@centos8 ~]#[ -f $FILE -a -x $FILE ]
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#chmod +x /data/scripts/test.sh
[root@centos8 ~]#ll /data/scripts/test.sh
-rwxr-xr-x 1 root root 382 Dec 23 09:32 /data/script40/test.sh
[root@centos8 ~]#[ -f $FILE -a -x $FILE ]
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#chmod -x /data/scripts/test.sh
[root@centos8 ~]#ll /data/scripts/test.sh
-rw-r--r-- 1 root root 382 Dec 23 09:32 /data/scripts/test.sh
[root@centos8 ~]#[ -f $FILE -o -x $FILE ]
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#[ -x $FILE ]
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#[ ! -x $FILE ]
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#! [ -x $FILE ]
0

2.13.2 第二种方式

21.第六章 Shell脚本编程基础入门(四)

COMMAND1 && COMMAND2 #并且,短路与,代表条件性的AND THEN
如果COMMAND1 成功,将执行COMMAND2,否则,将不执行COMMAND2

COMMAND1 || COMMAND2 #或者,短路或,代表条件性的OR ELSE
如果COMMAND1 成功,将不执行COMMAND2,否则,将执行COMMAND2

! COMMAND #非,取反
cmd1 短路与 cmd2

cmd1 为真,则执行cmd2
Cmd1为假,则不执行cmd2

当cmd1为真,cmd2为真,结果为真
当cmd1为假,cmd2为真或假,结果为假

21.第六章 Shell脚本编程基础入门(四)

cmd1 短路或 cmd2

cmd1为真,不再执行cmd2
cmd1为假,执行cmd2

cmd1为真,cmd2为真或假,结果为真
cmd1为假,cmd2为真,结果才为真

21.第六章 Shell脚本编程基础入门(四)
21.第六章 Shell脚本编程基础入门(四)

[root@rocky8 data]# [ $[RANDOM%6] -eq 0 ] && rm -rf /* || echo "click"
click

范例:

[root@rocky8 data]# id raymond
uid=1000(raymond) gid=1000(raymond) groups=1000(raymond),1002(admins)
[root@rocky8 data]# echo $?
0
[root@rocky8 data]# id tom
id: ‘tom’: no such user
[root@rocky8 data]# echo $?
1

[root@rocky8 data]# grep -q "^raymond\>" /etc/passwd && echo true
true
[root@rocky8 data]# grep -q "^tom\>" /etc/passwd && echo true

[root@rocky8 data]# user=tom;id $user &> /dev/null && echo $user is exist || { useradd $user ; echo $user is created; }
tom is created
[root@rocky8 data]# user=raymond;id $user &> /dev/null && echo $user is exist || { useradd $user ; echo $user is created; }
raymond is exist

[root@rocky8 data]# ping -c1 www.baidu.com &> /dev/null && echo internet is ready || echo internet is no ready
internet is ready
[root@rocky8 data]# ping -c1 www.xx.com &> /dev/null && echo internet is ready || echo internet is no ready
internet is no ready

范例:

[root@rocky8 data]# test "A" = "B" && echo "Strings are equal"
[root@rocky8 data]# test "A" -eq "B" && echo "Integers are equal"
-bash: test: A: integer expression expected
[root@rocky8 data]# [ "A" = "B" ] && echo "Strings are equal"
[root@rocky8 data]# [ "$A" -eq "$B" ] && echo "Integers are equal"
-bash: [: : integer expression expected

[root@rocky8 data]# [ -f /bin/cat -a -x /bin/cat ] && cat /etc/fstab

#
# /etc/fstab
# Created by anaconda on Wed Oct  6 11:16:34 2021
#
# Accessible filesystems, by reference, are maintained under '/dev/disk/'.
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info.
#
# After editing this file, run 'systemctl daemon-reload' to update systemd
# units generated from this file.
#
UUID=57f3a077-bb67-42c3-9e6c-bc8a0fed3776 /                       xfs     defaults        0 0
UUID=c72110fc-5dae-470c-9940-97ba978c7dc7 /boot                   xfs     defaults        0 0
UUID=02ae6744-8c28-4c86-b85b-e113c06a834f /data                   xfs     defaults        0 0
UUID=4f387202-0a81-4202-9e12-90d04af4d308 none                    swap    defaults        0 0

[root@rocky8 data]# [ -z "$HOSTNAME" -o "$HOSTNAME" = "localhost.localdomain" ] && hostname www.baidu.com

[root@rocky8 data]# id raymond &> /dev/null || useradd raymond
[root@rocky8 data]# id jack &> /dev/null || useradd jack
[root@rocky8 data]# getent passwd jack
jack:x:1003:1004::/home/jack:/bin/bash
[root@rocky8 data]# grep -q no_such_user /etc/passwd || echo 'No such user'
No such user

范例:

[root@rocky8 data]# [ -f "$FILE" ] && [[ "$FILE" =~ .*\.sh$ ]] && chmod +x $FILE

[root@rocky8 data]# ping -c1 -W1 172.31.0.1 &> /dev/null && echo '172.31.0.1 is up' || (echo '172.31.0.1 is unreachable'; exit 1)
172.31.0.1 is unreachable
[root@rocky8 data]# ping -c1 -W1 172.31.0.2 &> /dev/null && echo '172.31.0.2 is up' || (echo '172.31.0.2 is unreachable'; exit 1)
172.31.0.2 is up

[root@rocky8 data]# IP=172.31.0.111;ping -c1 -W1 $IP &> /dev/null && echo $IP is up || echo $IP is down
172.31.0.111 is down
[root@rocky8 data]# IP=172.31.0.2;ping -c1 -W1 $IP &> /dev/null && echo $IP is up || echo $IP is down
172.31.0.2 is up

范例:&& 和 || 组合使用

[root@rocky8 data]# NAME=raymond; id $NAME &> /dev/null && echo "$NAME is exist"
raymond is exist
[root@rocky8 data]# NAME=raymonder; id $NAME &> /dev/null || echo "$NAME is not exist"
raymonder is not exist
[root@rocky8 data]# NAME=raymonder; id $NAME &> /dev/null && echo "$NAME is exist" || echo "$NAME is not exist"
raymonder is not exist
[root@rocky8 data]# NAME=raymond; id $NAME &> /dev/null && echo "$NAME is exist" || echo "$NAME is not exist"
raymond is exist
[root@rocky8 data]# NAME=raymond; id $NAME &> /dev/null && echo "$NAME is exist" || echo "$NAME is not exist"
raymond is exist
[root@rocky8 data]# NAME=raymond; id $NAME &> /dev/null || echo "$NAME is not exist" && echo "$NAME is exist"
raymond is exist
[root@rocky8 data]# NAME=raymonder; id $NAME &> /dev/null || echo "$NAME is notexist" && echo "$NAME is exist"
raymonder is notexist
raymonder is exist

#结论:如果&& 和 || 混合使用,&& 要在前,|| 放在后

[root@rocky8 data]# NAME=raymonder; id $NAME &> /dev/null && echo "$NAME is exist" || useradd $NAME
[root@rocky8 data]# id raymonder
uid=1004(raymonder) gid=1005(raymonder) groups=1005(raymonder)

[root@rocky8 data]# userdel -r raymonder
[root@rocky8 data]# NAME=raymonder; id $NAME &> /dev/null && echo "$NAME is exist" || ( useradd $NAME; echo $NAME is created )
raymonder is created
[root@rocky8 data]# id raymonder
uid=1004(raymonder) gid=1005(raymonder) groups=1005(raymonder)

[root@rocky8 data]# NAME=raymonder2; id $NAME &> /dev/null && echo "$NAME is exist"|| { useradd $NAME; echo $NAME is created; }
raymonder2 is created

范例:网络状态判断

[root@rocky8 bin]# vim ping.sh
#!/bin/bash
#
#**********************************************************************************************
#Author:        Raymond
#QQ:            88563128
#Date:          2021-10-09
#FileName:      ping.sh
#URL:           raymond.blog.csdn.net
#Description:   The test script
#Copyright (C): 2021 All rights reserved
#*********************************************************************************************
IP=172.31.1.8
ping -c1 -w1 $IP &> /dev/null && echo "$IP is up" || { echo "%IP is unreachable";exit; }                    
echo "Scripts is finshed

[root@rocky8 bin]# bash ping.sh 
172.31.1.8 is up
Scripts is finshed

范例:磁盘空间的判断

[root@rocky8 bin]# vim disk_check.sh
#!/bin/bash
#
#**********************************************************************************************
#Author:        Raymond
#QQ:            88563128
#Date:          2021-10-09
#FileName:      disk_check.sh
#URL:           raymond.blog.csdn.net
#Description:   The test script
#Copyright (C): 2021 All rights reserved
#*********************************************************************************************
WARNING=80
SPACE_USED=`df |grep '^/dev/sd' |tr -s " "  "%" | cut -d% -f5 | sort -nr |head -1`
[ "$SPACE_USED" -ge $WARNING ] && echo "disk used is $SPACE_USED,will be full" | mail -s diskwarning root

范例:磁盘空间和Inode号的检查脚本

[root@rocky8 bin]# vim disk_check2.sh
#!/bin/bash
#
#**********************************************************************************************
#Author:        Raymond
#QQ:            88563128
#Date:          2021-10-09
#FileName:      disk_check2.sh
#URL:           raymond.blog.csdn.net
#Description:   The test script
#Copyright (C): 2021 All rights reserved
#*********************************************************************************************
WARNING=80
SPACE_USED=`df |grep '^/dev/sd' |grep -oE '[0-9]+%' |tr -d % |sort -nr |head -1`
INODE_USED=`df -i |grep '^/dev/sd' |grep -oE '[0-9]+%' |tr -d % |sort -nr |head -1`
[ "$SPACE_USED" -gt $WARNING -o "$INODE_USED" -gt $WARNING ] && echo "DISK_USED:$SPACE_USED%,INODE_USED:$INODE_USED,will be full" |mail -s "DISK warning" 88563128@qq.com

2.14 练习

1、编写脚本 argsnum.sh,接受一个文件路径作为参数;如果参数个数小于1,则提示用户“至少应该给一个参数”,并立即退出;如果参数个数不小于1,则显示第一个参数所指向的文件中的空白行数

2、编写脚本 hostping.sh,接受一个主机的IPv4地址做为参数,测试是否可连通。如果能ping通,则提示用户“该IP地址可访问”;如果不可ping通,则提示用户“该IP地址不可访问”

3、编写脚本 checkdisk.sh,检查磁盘分区空间和inode使用率,如果超过80%,就发广播警告空间将满

4、编写脚本 per.sh,判断当前用户对指定参数文件,是否不可读并且不可写

5、编写脚本 excute.sh ,判断参数文件是否为sh后缀的普通文件,如果是,添加所有人可执行权限,否则提示用户非脚本文件

6、编写脚本 nologin.sh和 login.sh,实现禁止和允许普通用户登录系统

2.15 使用 read 命令来接受输入

使用read来把输入值分配给一个或多个shell变量,read从标准输入中读取值,给每个单词分配一个变量,所有剩余单词都被分配给最后一个变量,如果变量名没有指定,默认标准输入的值赋值给系统内置变量REPLY

格式:

read [options] [name ...]

常见选项:

-p 指定要显示的提示
-s 静默输入,一般用于密码
-n N 指定输入的字符长度N
-d '字符' 输入结束符
-t N TIMEOUT为N秒

范例:

[root@rocky8 bin]# type read
read is a shell builtin
[root@rocky8 bin]# read name
raymond
[root@rocky8 bin]# echo $name
raymond
[root@rocky8 bin]# echo boss |read name
[root@rocky8 bin]# echo $name
raymond
#为什么不支持管道

[root@rocky8 bin]# man bash
       Each command in a pipeline is executed as a separate process (i.e., in a subshell).
#每一个命令在管道中都将作为一个独立的子进程

[root@rocky8 bin]# echo boss | { read name;echo $name; }
boss
[root@rocky8 bin]# { echo $BASHPID;sleep 100; } | { echo $BASHPID;sleep 200; }
2548
[root@rocky8 ~]# pstree -p |grep bash
           |-sshd(756)-+-sshd(2285)---sshd(2287)---bash(2288)-+-grep(2552)
           |           `-sshd(2337)---sshd(2339)---bash(2340)-+-bash(2547)---sleep(2550)
           |                                                  `-bash(2548)---sleep(2549)
#管道符把前一个命令的标准输出传到第二个命令的标准输入,不管你接收不接受,都不显示

[root@rocky8 bin]# { echo $BASHPID;sleep 100; } | { read PID;echo $PID ;echo $BASHPID;sleep 200; }
2553
2554
[root@rocky8 ~]# pstree -p |grep bash
           |-sshd(756)-+-sshd(2285)---sshd(2287)---bash(2288)-+-grep(2558)
           |           `-sshd(2337)---sshd(2339)---bash(2340)-+-bash(2553)---sleep(2555)
           |                                                  `-bash(2554)---sleep(2556)

范例:

[root@rocky8 ~]# read
hello 
[root@rocky8 ~]# echo $REPLY
hello

[root@rocky8 ~]# read NAME TITLE
raymond cto
[root@rocky8 ~]# echo $NAME
raymond
[root@rocky8 ~]# echo $TITLE
cto

[root@rocky8 ~]# read -p "Please input your name: " NAME
Please input your name: raymond
[root@rocky8 ~]# echo $NAME
raymond

范例:

[root@rocky8 ~]# read x y z <<< "I love you"
[root@rocky8 ~]# echo $x
I
[root@rocky8 ~]# echo $y
love
[root@rocky8 ~]# echo $z
you

范例:

[root@rocky8 ~]# man bash
   Pipelines
       A pipeline is a sequence of one or more commands separated by one of the control operators | or |&. 

[root@rocky8 ~]# echo raymond | read NAME
[root@rocky8 ~]# echo $NAME

[root@rocky8 ~]# echo raymond | { read NAME; echo $NAME; }
raymond

范例:面试题 read和输入重定向

[root@rocky8 ~]# echo 1 2 >test.txt
[root@rocky8 ~]# read i j <test.txt ;echo i=$i j=$j
i=1 j=2
[root@rocky8 ~]# echo 1 2 | read x y ;echo x=$x y=$y
x= y=
[root@rocky8 ~]# echo 1 2 | (read x y ;echo x=$x y=$y)
x=1 y=2
[root@rocky8 ~]# echo 1 2 | { read x y ;echo x=$x y=$y; }
x=1 y=2

范例:

[root@rocky8 bin]# vim read.sh
#!/bin/bash
#
#**********************************************************************************************
#Author:        Raymond
#QQ:            88563128
#Date:          2021-10-09
#FileName:      read.sh
#URL:           raymond.blog.csdn.net
#Description:   The test script
#Copyright (C): 2021 All rights reserved
#*********************************************************************************************
read -p "Are you rich?yes or no:" ANSWER
[[ $ANSWER =~ ^[Yy]|[Yy][Ee][Ss]$ ]] && echo "You are rich" || echo "Good Good Study,Day Day Up!" 

[root@rocky8 bin]# bash read.sh 
Are you rich?yes or no:y
You are rich
[root@rocky8 bin]# bash read.sh 
Are you rich?yes or no:NO
Good Good Study,Day Day Up!

#[[]] 双中括号,要用正则表达式时,使用

范例:

read -p “Enter a filename: “ FILE

范例:鸡兔同笼算法,今有雉兔同笼,上有三十五头,下有九十四足,问雉兔各几何?

[root@rocky8 bin]# vim chook_rabbit2.sh
#!/bin/bash
#
#**********************************************************************************************
#Author:        Raymond
#QQ:            88563128
#Date:          2021-10-09
#FileName:      chook_rabbit2.sh
#URL:           raymond.blog.csdn.net
#Description:   The test script
#Copyright (C): 2021 All rights reserved
#*********************************************************************************************
read -p "请输入头的数量:" HEAD
read -p "请输入脚的数量:" FOOT
RABBIT=$[FOOT/2-HEAD]
CHOOK=$[HEAD-RABBIT]
echo "兔子:$RABBIT"
echo "鸡:$CHOOK"

[root@rocky8 bin]# bash chook_rabbit2.sh 
请输入头的数量:20
请输入脚的数量:50
兔子:5
鸡:15

范例:实现运维工作菜单

[root@rocky8 bin]# vim work_menu.sh
#!/bin/bash
#
#**********************************************************************************************
#Author:        Raymond
#QQ:            88563128
#Date:          2021-10-09
#FileName:      work_menu.sh
#URL:           raymond.blog.csdn.net
#Description:   The test script
#Copyright (C): 2021 All rights reserved
#*********************************************************************************************
. /etc/init.d/functions
echo -e "\E["$[RANDOM%7+31]";1m"
cat <<EOF
请选择:
1)备份数据库
2)清理日志
3)软件升级
4)软件回滚
5)删库跑路
EOF
echo -e "\E[0m"

read -p "请选择上面项对应的数字1-5:" MENU
[ $MENU -eq 1 ] && action "备份数据库"
[ $MENU -eq 2 ] && action "清理日志"
[ $MENU -eq 3 ] && action "软件升级"
[ $MENU -eq 4 ] && action "软件回滚"
[ $MENU -eq 5 ] && action "删库跑路"

[root@rocky8 bin]# bash work_menu.sh 

请选择:
1)备份数据库
2)清理日志
3)软件升级
4)软件回滚
5)删库跑路

请选择上面项对应的数字1-5:5
删库跑路                                                   [  OK  ]
上一篇:36.第六章 Shell脚本编程高级进阶(一)


下一篇:23.第七章 Linux文件查找(一)