[华为云在线课程][Shell脚本编程基础][第二章Shell脚本语言的基本用法][3算术运算及测试][学习笔记]
格式化输出printf
格式
printf "指定的格式" "文本1" "文本2"......
常用格式替换符
%s 字符串
%f 浮点格式
%b 相对应的参数中包含转义字符时,可以使用此替换符进行替换,对应的转义字符会被转义
%c ASCII字符,即显示对应参数的第一个字符
%d,%i 十进制整数
%o 八进制值
%u 不带正负号的十进制值
%x 十六进制(a-f)
%X 十六进制(A-F)
%% 表示%本身
说明:%#s中的#数字代表此替换符中的输出字符宽度,不足补空格,默认是右对齐,%-10s表示10个字符宽,-表示左对齐
常用转义字符
\a 警告字符,通常为ASCII的BEL字符
\b 后退
\f 换页
\n 换行
\r 回车
\t 水平制表符
\v 垂直制表符
\ 表示\本身
例子:
[root@localhost Code]# printf '%s\n' 1 2 3 4
1
2
3
4
[root@localhost Code]# printf '%f\n' 1 2 3 4
1.000000
2.000000
3.000000
4.000000
[root@localhost Code]# printf '%.2f\n' 1 2 3 4
1.00
2.00
3.00
4.00
[root@localhost Code]# printf '(%s)' 1 2 3 4;echo
(1)(2)(3)(4)
[root@localhost Code]# printf ' (%s) ' 1 2 3 4;echo
(1) (2) (3) (4)
[root@localhost Code]# printf ' (%s) \n' 1 2 3 4;echo
(1)
(2)
(3)
(4)
[root@localhost Code]# printf '%s %s\n' 1 2 3 4
1 2
3 4
[root@localhost Code]# printf '%s %s %s\n' 1 2 3 4
1 2 3
4
#%-10s 表示宽度10个字符,左对齐
[root@localhost Code]# printf "%-10s %-10s %-4s %s \n" 姓名 性别 年龄 体重 小明 男 20 70 小红 女 18 50
姓名 性别 年龄 体重
小明 男 20 70
小红 女 18 50
#将十进制的17转换成16进制数
[root@localhost Code]# printf "%X" 17;echo
11
#将十六进制C转换为十进制
[root@localhost Code]# printf "%d\n" 0xC
12
[root@localhost Code]# VAR="Hello World";printf "\033[31m%s\033[0m\n" $VAR
Hello
World
[root@localhost Code]# VAR="Hello World";printf "\033[31m%s\033[0m\n" "$VAR"
Hello World
算术运算
shell允许在某些情况下对算术表达式进行求值,比如:let和declare内置命令,(())复合命令和算术拓展。求值以固定宽度的整数进行,不检查溢出,尽管除以0被困并标记为错误。运算符及其优先级,关联性和值与C语言相同。以下运算符列表分组为等优先级运算符级别。级别按降序排列优先。
注意:bash只支持整数,不支持小数
* / % multiplication,division,remainder,%表示取模,即取余数
+ - addition,subtraction
i++ i-- variable post-increment and post-decrement
++i --i variable pre-increment and post-increment
= *= /= %= += -= <<= >>= &= ^= |= assignment
- + unary minus and plus
! ~ logical and bitwise negation
** exponentiation
<< >> left and right bitwise shifts
<= >= < > comparison
== != equality and inequality
& bitwise AND
| bitwise OR
^ bitwise exclusive OR
&& logical AND
|| logical OR
expr?expr:expr conditional operator
expr1,expr2 comma
乘法符号有些场景中需要转义
实现算术运算
(1)let var=算术表达式
(2)((var=算术表达式)) 和上面等价
(3)var=$[算术表达式]
(4)var=$((算术表达式))
(5)var=$(expr arg1 arg2 arg3 ...)
(6)declare -i var=数值
(7)echo '算术表达式' | bc
内建的随机数生成器变量:
$RANDOM 取值范围:0-32767
例子:
#生成 0-49 之间随机数
echo $[$RANDOM%50]
#随机字体颜色
[root@localhost Code]# echo -e "\033[1;$[RANDOM%7+31]m hello \033[0m"
hello
增强型赋值:
+= i+=10 相当于i=i+10
-= i-=j 相当于i=i-j
*=
/=
%=
++ i++ ++i 相当于i=i+1
-- i-- --i 相当于i=i-1
格式:
let varOPERvalue
例子:
[root@localhost Code]# let i=10*2
[root@localhost Code]# echo $i
20
[root@localhost Code]# ((j=i+10))
[root@localhost Code]# echo $j
30
例子:
#自加3后赋值
[root@localhost Code]# let count+=3
[root@localhost Code]# i=10
[root@localhost Code]# let i+=20
[root@localhost Code]# echo $i
30
[root@localhost Code]# j=20
[root@localhost Code]# let i*=j
[root@localhost Code]# echo $i
600
例子:
#自增,自减
[root@localhost Code]# unset i j;i=1;let j=i++;echo "i=$i,j=$j"
i=2,j=1
[root@localhost Code]# unset i j;i=1;let j=++i;echo "i=$i,j=$j"
i=2,j=2
例子:
[root@localhost Code]# expr 2 *3
expr: syntax error
[root@localhost Code]# expr 2\* 3
expr: syntax error
[root@localhost Code]# expr 2 \* 3
6
例子:
[root@localhost Code]# echo "scale=3;20/3"|bc
6.666
例子:
[root@localhost Code]# i=10
[root@localhost Code]# j=20
[root@localhost Code]# declare -i result=i*j
[root@localhost Code]# echo $result
200
例子:计算鸡兔同笼,上有35头,下有94脚,问鸡兔各有多少只?
[root@localhost Code]# cat chook_rabbit.sh
#!/bin/bash
HEAD=$1
FOOT=$2
RABBIT=$(((FOOT-HEAD-HEAD)/2))
CHOOK=$[HEAD-RABBIT]
echo RABBIT:$RABBIT
echo CHOOK:$CHOOK
[root@localhost Code]# ./chook_rabbit.sh 35 94
RABBIT:12
CHOOK:23
逻辑运算
true,false
1,真
0,假
#注意,以上为二进制
&(与):与0相与,结果为0,和1相与,结果保留原值
1 & 1 = 1
1 & 0 = 0
0 & 1 = 0
0 & 0 = 0
|(或):和1相或结果为1,和0相或,结果保留原值
1 | 1 = 1
1 | 0 = 1
0 | 1 = 1
0 | 0 = 0
!(非)
! 1 = 0 ! true
! 0 = 1 ! false
^(异或)
#异或的两个值,相同为假,不同为真。两个数字X,Y异或得到结果Z,Z再和任意两者之一X异或,将得出另一个值Y
0 ^ 0 = 0
0 ^ 1 = 1
1 ^ 0 = 1
1 ^ 1 = 0
例子:
[root@localhost Code]# true
[root@localhost Code]# echo $?
0
[root@localhost Code]# false
[root@localhost Code]# echo $?
1
[root@localhost Code]# !true
true
[root@localhost Code]# ! true
[root@localhost Code]# echo $?
1
[root@localhost Code]# ! false
[root@localhost Code]# echo $?
0
例子:变量互换
[root@localhost Code]# x=10;y=20;temp=$x;x=$y;y=$temp;echo x=$x,y=$y
x=20,y=10
[root@localhost Code]# x=10;y=20;x=$[x^y];y=$[x^y];x=$[x^y];echo x=$x,y=$y
x=20,y=10
短路运算
短路与
CMD1 短路与 CMD2
第一个CMD1结果为真 (1),第二个CMD2必须要参与运算,才能得到最终的结果
第一个CMD1结果为假 (0),总的结果必定为0,因此不需要执行CMD2
短路或
CMD1 短路或 CMD2
第一个CMD1结果为真 (1),总的结果必定为1,因此不需要执行CMD2
第一个CMD1结果为假 (0),第二个CMD2必须要参与运算,才能得到最终的结果
条件测试命令
条件测试:判断某需求是否满足,需要由测试机制来实现。专用的测试表达式需要由测试命令辅助完成测试过程,实现评估布尔声明,以使用在条件性环境下进行执行
若真,则状态码变量$?
返回0
若假,则状态码变量$?
返回1
条件测试命令
- test EXPRESSION
- [EXPRESSION] #和test等价,建议使用[]
- [[EXPRESSION]]相关于增强版的[]
注意:EXPRESSION前后必须有空白字符
帮助:
[root@localhost Code]# type [
[ is a shell builtin
[root@localhost Code]# 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 `['.
[[ ... ]]: [[ expression ]]
Execute conditional command.
[root@localhost Code]# help test
test: test [expr]
Evaluate conditional expression.
Exits with a status of 0 (true) or 1 (false) depending on
the evaluation of EXPR. Expressions may be unary or binary. Unary
expressions are often used to examine the status of a file. There
are string operators and numeric comparison operators as well.
The behavior of test depends on the number of arguments. Read the
bash manual page for the complete specification.
变量测试
#判断 NAME 变量是否定义
[ -v NAME ]
#判断 NAME 变量是否定义并且是名称引用,bash 4.4新特性
[ -R NAME ]
例子:
[root@localhost Code]# unset x
[root@localhost Code]# test -v x
[root@localhost Code]# echo $?
1
[root@localhost Code]# unset x
[root@localhost Code]# echo $?
0
[root@localhost Code]# x=10
[root@localhost Code]# test -v x
[root@localhost Code]# echo $?
0
[root@localhost Code]# test -v y | echo $?
0
#注意[ ]需要空格,否则会报下面错误
[root@localhost Code]# [-v y]
-bash: [-v: command not found
[root@localhost Code]# [ -v y]
-bash: [: missing `]'
[root@localhost Code]# [ -v y ]
[root@localhost Code]# echo $?
0
数值测试
-eq 是否等于
-ne 是否不等于
-gt 是否大于
-ge 是否大于等于
-lt 是否小于
-le 是否小于等于
例子:
[root@localhost Code]# i=10
[root@localhost Code]# j=8
[root@localhost Code]# [ $i -lt $j ]
[root@localhost Code]# echo $?
1
[root@localhost Code]# [ $i -gt $j ]
[root@localhost Code]# echo $?
0
[root@localhost Code]# [ i -gt j ]
-bash: [: i: integer expression expected
算术表达式比较
==
!=
<=
>=
<
>
例子:
[root@localhost Code]# x=10;y=10;((x==y));echo $?
0
[root@localhost Code]# x=10;y=20;((x==y));echo $?
1
[root@localhost Code]# x=10;y=20;((x!=y));echo $?
0
[root@localhost Code]# x=10;y=10;((x!=y));echo $?
1
例子:
[root@localhost Code]# x=10;y=20;((x>y));echo $?
1
[root@localhost Code]# x=10;y=20;((x<y));echo $?
0
字符串测试
test和[]用法
-z STRING 字符串是否为空,没定义或空为真,不空为假
-n STRING 字符串是否不空,不空为真,空为假
STRING 同上
STRING1 = STRING2 是否等于,注意=前后有空格
STRING1 != STRING2 是否不等于
> ASCII码是否大于ASCII码
< ASCII码是否小于ASCII码
[[]]用法
[[ expression ]] 用法
== 左侧字符串是否和右侧的PATTERN相同
注意:此表达式用于[[ ]]中,PATTERN为通配符
=~ 左侧字符串是否能够被右侧的正则表达式的PATTERN所匹配
注意:此表达式用于[[]]中,扩展的正则表达式
建议:当使用正则表达式或通配符使用[[]],其他情况一般使用[]
例子:使用[]
[root@localhost Code]# unset str
[root@localhost Code]# [ -z "$str" ]
[root@localhost Code]# echo $?
0
[root@localhost Code]# str=""
[root@localhost Code]# [ -z "$str" ]
[root@localhost Code]# echo $?
0
[root@localhost Code]# str=" "
[root@localhost Code]# [ -z "$str" ]
[root@localhost Code]# echo $?
1
[root@localhost Code]# [ -z "$str" ]
[root@localhost Code]# echo $?
1
[root@localhost Code]# [ "$str" ]
[root@localhost Code]# echo $?
0
[root@localhost Code]# str1=hello
[root@localhost Code]# str2=world
[root@localhost Code]# [ $str1 = $str2 ]
[root@localhost Code]# echo $?
1
[root@localhost Code]# str2=hello
[root@localhost Code]# [ $str1 = $str2 ]
[root@localhost Code]# echo $?
0
例子:在比较字符串时,建议变量放在""中
[root@localhost Code]# NAME="I love Linux"
[root@localhost Code]# [ $NAME ]
-bash: [: love: binary operator expected
[root@localhost Code]# [ "$NAME" ]
[root@localhost Code]# echo $?
0
[root@localhost Code]# [ I love Linux ]
-bash: [: love: binary operator expected
例子:[[]]和通配符
[root@localhost Code]# FILE="a*"
[root@localhost Code]# echo $FILE
arg.sh a.sh
[root@localhost Code]# [[ $FILE==a* ]]
[root@localhost Code]# echo $?
0
[root@localhost Code]# FILE="ab"
[root@localhost Code]# [[ $FILE==a* ]]
[root@localhost Code]# echo $?
0
#[[]]中如果不想使用通配符*,只想表达*本身,可以用" "引起来,也可以使用转义符
[root@localhost Code]# [[ FILE == a"*" ]]
[root@localhost Code]# echo $?
1
[root@localhost Code]# [[ FILE == a\* ]]
[root@localhost Code]# echo $?
1
#通配符?
[root@localhost Code]# FILE=abc
[root@localhost Code]# [[ $FILE == ??? ]]
[root@localhost Code]# echo $?
0
[root@localhost Code]# FILE=abcd
[root@localhost Code]# [[ $FILE == ??? ]]
[root@localhost Code]# echo $?
1
#通配符
[root@localhost Code]# NAME="linux"
[root@localhost Code]# [[ "$NAME" == linux* ]]
[root@localhost Code]# echo $?
0
[root@localhost Code]# [[ "$NAME" == "linux*" ]]
[root@localhost Code]# echo $?
1
[root@localhost Code]# NAME="linux*"
[root@localhost Code]# [[ "$NAME" == "linux*" ]]
[root@localhost Code]# echo $?
0
#结论:[[ == ]] == 右侧的 * 作为通配符,不要加"",只想作为*,需要加""或者转义
例子:判断合理的考试成绩
[root@localhost Code]# SCORE=101
[root@localhost Code]# [[ $SCORE =~ 100|[0-9]{1,2} ]]
[root@localhost Code]# echo $?
0
[root@localhost Code]# [[ $SCORE =~ ^(100|[0-9]{1,2})$ ]]
[root@localhost Code]# echo $?
1
[root@localhost Code]# SCORE=10
[root@localhost Code]# [[ $SCORE =~ ^(100|[0-9]{1,2})$ ]]
[root@localhost Code]# echo $?
0
[root@localhost Code]# SCORE=abc
[root@localhost Code]# [[ $SCORE =~ ^(100|[0-9]{1,2})$ ]]
[root@localhost Code]# echo $?
1
文件测试
存在性测试
-a FILE 同 -e
-e FILE 文件存在性测试,存在为真,否则为假
-b FILE 是否存在且为块设备文件
-c FILE 是否存在且为字符设备文件
-d FILE 是否存在且为目录文件
-f FILE 是否存在且为普通文件
-h FILE 或 -L FILE 是否存在且为符号链接文件
-p FILE 是否存在且为命名管道文件
-s FILE 是否存在且为套接字文件
例子:
#文件是否存在
[root@localhost Code]# [ -a /home/hello/Code/hello ]
[root@localhost Code]# echo $?
1
[root@localhost Code]# [ -a /home/hello/Code/a.sh ]
[root@localhost Code]# echo $?
0
文件权限测试:
-r FILE 是否存在且可读
-w FILE 是否存在且可写
-x FILE 是否存在且可执行
-u FILE 是否存在且拥有suid权限
-g FILE 是否存在且拥有sgid权限
-k FILE 是否存在且拥有sticky权限
注意:最终结果由用户对文件的实际权限决定,而非文件属性决定。
例如将写权限关闭,但是root用户还是能执行操作。
文件属性测试
-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
关于 () 和 {}
(CMD1;CMD2;…)和{CMD1;CMD2;…;} 都可以将多个命令组合在一起,批量执行
man bash
( list )会开启子shell,并且list中变量赋值及内部命令执行后,将不再影响后续的环境
帮助查看:man bash 搜索(list)
{ list; }不会开启子shell,在当前shell中运行,会影响当前shell环境
帮助查看:man bash 搜索{ list; }
组合测试条件
第一种方式 []
[ EXPRESSION1 -a EXPRESSION2 ] 并且,EXPRESSION1和EXPRESSION2都是真,结果才真
[ EXPRESSION1 -o EXPRESSION2 ] 或者,EXPRESSION1和EXPRESSION2只要一个为真,结果就为真
[ ! EXPRESSION ] 取反
说明:-a 和 -o 需要使用测试命令进行,[[]]不支持
第二种方式
COMMAND1 && COMMAND2 并且,短路与,代表条件性的AND THEN
如果COMMAND1成功,将执行COMMAND2,否则,将不执行COMMAND2
COMMAND1 || COMMAND2 或者,短路或,代表条件性的OR THEN
如果COMMAND1成功,将不执行COMMAND2,否则,将执行COMMAND2
!COMMAND 非,取反
注意:如果&&和||混合使用,&&要在前,||要在后
#Linux版俄罗斯轮盘
[ $[RANDOM%6] -eq 0 ] && rm -rf /* || echo "You are lucky"
使用read命令来接受输入
使用read来把输入值分配给一个或多个shell变量,read从标准输入中读取值,给每个单词分配一个变量,所有剩余单词都被分配给最后一个变量,如果变量名没有指定,默认标准输入的值赋值给系统内置变量REPLY
格式:
read [options] [name,...]
常见选项:
-p 指定要显示的提示
-s 静默输入,一般用于密码
-n N 指定输入的字符长度N
-d '字符' 输入结束符
例子:
[root@localhost Code]# read x y z <<< "I love you"
[root@localhost Code]# echo $x
I
[root@localhost Code]# echo $y
love
[root@localhost Code]# echo $z
you
例子:判断用户输入的是否为YES
[root@localhost Code]# cat yesorno.sh
#!/bin/bash
read -p "Please input yes or no: " input
answer=`echo $input|tr 'A-Z' 'a-z'`
[ $answer = 'yes' -o $answer = 'y' ] && echo YES
[ $answer = 'no' -o $answer = 'n' ] && echo NO
[root@localhost Code]# cat yesorno2.sh
#!/bin/bash
read -p "Please input yes or no: " input
[[ $input =~ ^([Yy][Ee][Ss]|[Yy])$ ]] && echo YES
[[ $input =~ ^([Nn][Oo]|[Nn])$ ]] && echo NO
- 点赞
- 收藏
- 关注作者
评论(0)