1、shell中的测试条件
在Shell脚本中,可以使用各种条件测试来评估条件的真假。下面是一些常见的Shell测试条件:
字符串比较:
=:判断两个字符串是否相等。
!=:判断两个字符串是否不相等。
-z:判断字符串是否为空。
-n:判断字符串是否非空。
文件比较:
-e:判断文件是否存在。
-f:判断文件是否为普通文件。
-d:判断文件是否为目录。
-r:判断文件是否可读。
-w:判断文件是否可写。
-x:判断文件是否可执行。
数值比较:
-eq:判断两个数是否相等。
-ne:判断两个数是否不相等。
-gt:判断一个数是否大于另一个数。
-lt:判断一个数是否小于另一个数。
-ge:判断一个数是否大于等于另一个数。
-le:判断一个数是否小于等于另一个数。
逻辑运算:
-a:逻辑与操作符,用于组合多个条件的逻辑与。
-o:逻辑或操作符,用于组合多个条件的逻辑或。
!:逻辑非操作符,用于取反一个条件。
3、第一种方式 [ ]
[ EXPRESSION1 -a EXPRESSION2 ] 并且,EXPRESSION1和EXPRESSION2都是真,结果才为真
[ EXPRESSION1 -o EXPRESSION2 ] 或者,EXPRESSION1和EXPRESSION2只要有一个真,结果就为
真
[ ! EXPRESSION ] 取反
说明: -a 和 -o 需要使用测试命令进行,[[ ]] 不支持
这些条件可以与if语句结合使用,根据条件的真假执行相应的代码块。例如:
if [ -f file.txt ]; then
echo "file.txt 存在并且是一个普通文件"
fi
if [ "$str1" = "$str2" ]; then
echo "str1 和 str2 相等"
fi
if [ $num1 -gt $num2 ]; then
echo "num1 大于 num2"
fi
请注意,条件测试的语法可能因不同的Shell版本而略有差异。以上示例基于Bash Shell。
例2:
[ -f /bin/cat -a -x /bin/cat ]
该条件测试检查 /bin/cat 是否存在且可执行。
解析该条件测试的逻辑:
[ -f /bin/cat ]:检查 /bin/cat 是否是一个存在的文件(普通文件)。
-a:逻辑与操作符,用于组合多个条件的逻辑与。
[ -x /bin/cat ]:检查 /bin/cat 是否是可执行文件。
如果两个条件都为真,则整个条件测试为真,返回退出状态码为0;否则,条件测试为假,返回非零的退出状态码。
请注意,条件测试使用方括号 [ ] 进行包裹,并且每个条件之间用空格分隔。在某些Shell中,也可以使用双括号 [[ ]] 或 test 命令进行条件测试。
这个条件测试可以在Shell脚本中作为条件语句的一部分使用,根据条件的真假执行相应的代码块。例如:
if [ -f /bin/cat -a -x /bin/cat ]; then
echo "/bin/cat 存在并且可执行"
else
echo "/bin/cat 不存在或不可执行"
fi
2、第二种方式 [[ ]]
COMMAND1 && COMMAND2 #并且,短路与,代表条件性的AND THEN
如果COMMAND1 成功,将执行COMMAND2,否则,将不执行COMMAND2
COMMAND1 || COMMAND2 #或者,短路或,代表条件性的OR ELSE
如果COMMAND1 成功,将不执行COMMAND2,否则,将执行COMMAND2
! COMMAND #非,取反
在 Shell 脚本中,“&&” 是一个逻辑操作符,用于在执行多条命令时,判断前面的命令是否执行成功,如果成功,则继续执行后面的命令,否则停止执行后面的命令。
下面是一个简单的示例,演示了如何使用 “&&” 操作符来执行多个命令:
#!/bin/bash
mkdir mydir && cd mydir && touch myfile.txt
这个脚本中,使用了三个命令:mkdir、cd 和 touch。第一个命令 mkdir 用于创建一个名为 mydir 的目录,如果该命令执行成功,则接着执行第二个命令 cd,将当前工作目录切换到 mydir 目录下,如果第二个命令执行成功,则继续执行第三个命令 touch,用于创建一个名为 myfile.txt 的空文件。
[root@VM-4-14-centos ~]# NAME=root; id $NAME &> /dev/null && echo "$NAME is exist"
root is exist
[root@VM-4-14-centos ~]# NAME=rooter; id $NAME &> /dev/null && echo "$NAME is exist"
如果执行该脚本时,其中任何一个命令执行失败,后续的命令都不会被执行。
除了 “&&” 操作符之外,Shell 脚本还支持其他的逻辑操作符,例如 “||” 和 “;”。“||” 用于判断前面的命令是否执行失败,如果失败,则执行后面的命令;“;” 用于依次执行多个命令,不管前面的命令是否执行成功。
下面是一个示例,演示了如何使用 “||” 和 “;” 操作符:
#!/bin/bash
mkdir mydir || echo "创建目录失败"
cd mydir ; touch myfile.txt ; echo "文件创建完成"
在这个脚本中,第一个命令 mkdir 用于创建一个名为 mydir 的目录,如果该命令执行失败,则执行第二个命令 echo “创建目录失败”;第二个命令 cd 用于切换到 mydir 目录下,后面的两个命令 touch 和 echo “文件创建完成” 则使用 “;” 操作符连接在一起,依次执行。
&& ||并用
[root@VM-4-14-centos ~]# NAME=rooter; id $NAME &> /dev/null && echo "$NAME is exist" || echo "$NAME is not exist"
rooter is not exist
[root@VM-4-14-centos ~]# NAME=root; id $NAME &> /dev/null && echo "$NAME is exist" || echo "$NAME is not exist"
root is exist
逻辑操作符是 Shell 脚本中非常有用的一种工具,可以帮助我们更加灵活地控制命令的执行顺序和流程。当我们需要在一个脚本中执行多个命令,并根据前面的命令执行结果来确定后续的操作时,逻辑操作符就显得尤为重要了。
3、shell中的$1和$2
在Shell脚本中,$1和$2是特殊的变量,用于表示脚本接收的命令行参数。
$1代表第一个命令行参数。
$2代表第二个命令行参数。
当你在Shell中执行一个脚本时,可以通过命令行传递参数给脚本。这些参数可以是任意数量,用空格分隔。
例如,假设你有一个名为script.sh的Shell脚本,内容如下:
#!/bin/bash
echo "第一个参数:$1"
echo "第二个参数:$2"
当你执行这个脚本并传递两个参数时,如下所示:
$ ./script.sh hello world
脚本将输出:
第一个参数:hello
第二个参数:world
这样,你就可以在脚本中使用$1和$2来获取命令行传递的参数值,以便在脚本中进行相应的处理。
4、read
在 Linux 中,read
是一个用于从标准输入或其他文件描述符中读取输入的命令或系统调用。它可以从用户输入或文件中读取数据,并将其存储到一个变量中供后续处理。
作为一个命令,read
可以在终端中使用,用于从用户输入中读取数据。例如,您可以使用以下语法从用户输入中读取一个字符串:
read variable_name
在执行上述命令后,read
会等待用户输入数据,并将输入的内容存储到名为 variable_name
的变量中。您可以根据需要将变量用于后续的操作。
除了作为命令使用外,read
也是一个系统调用(system call),在 shell 脚本或编程语言中通过调用该系统调用来实现读取输入的功能。系统调用的用法和命令类似,可以从标准输入或其他文件描述符中读取数据,并将其存储到指定的变量中。
需要注意的是,read
命令或系统调用在读取输入时通常会等待用户的响应,因此在脚本或程序中使用时,可能需要适当处理超时或错误情况,以避免出现无限等待的情况。
例1:
通过用户输入“yes”或者“no”来输出不同的内容
#! /bin/bash
# rich 富有的意思
# read -p 参数表示不换行
read -p "are you rich? yes or no: " ANSWER
[ $ANSWER = "yes" -o $ANSWER = "y" ] && echo "You are rich" || echo "good good study"
# 执行
[root@VM-4-14-centos shell]# bash read.sh
are you rich? yes or no: yes
You are rich
[root@VM-4-14-centos shell]# bash read.sh
are you rich? yes or no: y
You are rich
[root@VM-4-14-centos shell]# bash read.sh
are you rich? yes or no: no
good good study
这种情况范围太小,有的用户可能会输入Y,或者Yes等,需改造如下:
[root@VM-4-14-centos shell]# vim read.sh
#! /bin/bash
read -p "Are you rich? yes or no: " ANSWER
[[ $ANSWER =~ ^[Yy]|[Yy][Ee][Ss]$ ]] && echo "You are rich" || echo "good good study"
# 执行
[root@VM-4-14-centos shell]# bash read1.sh Yes
Are you rich? yes or no: Yes
You are rich
[root@VM-4-14-centos shell]# bash read1.sh
Are you rich? yes or no: yES
You are rich
5、[0-9]
表达式"[0-9]"表示一个字符范围,即包含从0到9的所有数字。这种表示方法常用于正则表达式或模式匹配中,用于匹配任何一个数字字符。可以将其理解为匹配数字的通用模式。
例如,如果你使用这个表达式来搜索一个字符串,它将匹配任何包含0到9之间的数字的字符。如果字符串中有数字字符"3",“5”,"8"等,它们都会被匹配到。
这个表达式也可以简写为"\d",其中"\d"代表任何一个数字字符。所以,"[0-9]“和”\d"在匹配数字字符方面是等效的。
6、{1,3}
表达式"{1,3}"表示前面的元素可以重复出现1到3次。这种表示方法常用于正则表达式或模式匹配中,用于指定重复次数的范围。
例如,如果你有一个表达式如下:
“A{1,3}B”
这个表达式将匹配以下字符串之一:
“AB”:A出现1次,B出现1次。
“AAB”:A出现2次,B出现1次。
“AAAB”:A出现3次,B出现1次。
但它不会匹配以下字符串:
“A”:因为B没有出现。
“AAABBB”:因为B出现了多于1到3次的次数。
因此,"{1,3}“表示前面的元素(在上述示例中是"A”)可以重复出现1到3次,而不会匹配超过或少于这个范围的次数。
7、if条件语句
例1:
#! /bin/bash
read -p "输入身高(单位m):" HIGH
if [[ ! "$HIGH" =~ ^[0-2]\.?[0-9]{,2}$ ]];then
echo "输入错误的身高"
exit 1
fi
read -p "请输出体重(kg为单位):" WEIGHT
if [[ ! "$WEIGHT" =~ ^[0-9]{1,3}$ ]];then
echo "输入错误的体重"
exit 1
fi
BMI=`echo $WEIGHT/$HIGH^2|bc`
if [ $BMI -le 18 ];then
echo "你太瘦了,多吃点"
elif [ $BMI -lt 24 ];then
echo "你身材太好了"
else
echo "太胖了,加强运动"
fi
8、case 语句
语法:
case 引用变量 in
PAT1)
分支1
;;
PAT2)
分支2
;;
PAT3)
分支3
;;
...
*)
默认分支
;;
esac
case中支持的通配符
*:任意长度字符
?:任意单字符
[]:任意范围内的任意字符
|:或,如x或y
9、for 循环
语法:
# 三种写法
for NAME [in WORDS ... ] ; do COMMANDS; done
for 变量名 in 列表;do
循环体
done
for 变量名 in 列表
do
循环体
done
例1:
[root@VM-4-14-centos shell]# for i in 1 2 3 4 5 6 ; do echo i=$i; done
i=1
i=2
i=3
i=4
i=5
i=6
[root@VM-4-14-centos shell]# for i in {1..10} ; do echo i=$i; done
i=1
i=2
i=3
i=4
i=5
i=6
i=7
i=8
i=9
i=10
例2:
# 步长为 2,就是每次循环增加 2
[root@VM-4-14-centos shell]# for i in {1..10..2} ; do echo i=$i; done
i=1
i=3
i=5
i=7
i=9
[root@VM-4-14-centos shell]# for i in {0..10..2} ; do echo i=$i; done
i=0
i=2
i=4
i=6
i=8
i=10
[root@VM-4-14-centos shell]# for i in {001..10..2} ; do echo i=$i; done
i=001
i=003
i=005
i=007
i=009
例3:求和:1-100累加
[root@VM-4-14-centos shell]# sum=0;for i in {1..100};do let sum+=i;done; echo sum=$sum
sum=5050
[root@VM-4-14-centos shell]# vim leijia.sh
#! /bin/bash
# 设置初始值
sum=0
for i in {1..100};do
# sum+=i,+= 是一个复合赋值运算符,表示将右侧的值与左侧的值相加,并将结果赋值给左侧的变量。
let sum+=i
done
echo sum=$sum
# 其他方法
# seq -s+: -s 选项用于指定输出序列中数字之间的分隔符(separator)。+ 是作为分隔符的具体字符。
[root@VM-4-14-centos shell]# seq -s+ 100|bc
5050
例4:算出传参的和
# $@是指所有传入的参数
[root@VM-4-14-centos shell]# vim for_sum.sh
#! /bin/bash
sum=0
for i in $@ ;do
let sum+=i
done
echo "sum=$sum"
# 执行结果
[root@VM-4-14-centos shell]# ./for_sum.sh 1 2
sum=3
[root@VM-4-14-centos shell]# ./for_sum.sh 1 2 3
sum=6
例5:99 乘法表
[root@VM-4-14-centos shell]# vim 9x9.sh
#! /bin/bash
# 外层循环for i in {1..9}循环遍历从1到9的数值,并将每个值赋给变量i。
# 内层循环for j in $(seq $i)循环使用seq命令遍历从1到i的数值,并将每个值赋给变量j。
# \t 表示水平制表符(Tab),它是一种特殊的转义序列。当 echo 命令遇到 \t 时,它会在输出中插入>一个制表符,用于产生水平对齐的效果。
# echo 命令中,\c 是一个特殊的转义序列,它用于在输出中取消换行符。当 echo 命令遇到 \c 时,它>会使得输出结束后不会自动添加换行符。
# seq 9按照顺序生产1到9
for i in {1..9};do
for j in `seq $i`;do
echo -e "$jx$i=$((j*i))\t\c"
done
echo
done
# 执行
[root@VM-4-14-centos shell]# ./9x9.sh
1=1
2=2 2=4
3=3 3=6 3=9
4=4 4=8 4=12 4=16
5=5 5=10 5=15 5=20 5=25
6=6 6=12 6=18 6=24 6=30 6=36
7=7 7=14 7=21 7=28 7=35 7=42 7=49
8=8 8=16 8=24 8=32 8=40 8=48 8=56 8=64
9=9 9=18 9=27 9=36 9=45 9=54 9=63 9=72 9=81