AI智能
改变未来

shell 脚本 – 格式化输出、运算符以及read输入

格式化输出、运算符以及read输入

  • 格式化输出 printf
  • 运算符
  • 算术运算符
  • 逻辑运算符
  • 短路运算
  • 关系运算符
  • 条件测试命令
    • 数值测试
    • 字符串测试
    • 文件测试
    • 组合测试
  • 接受输入 read
  • 格式化输出 printf

    格式

    printf \"指定格式\" \"文本1\" \"文本2\"

    常用格式替换符

    %s	以字符串形式输出%f	以浮点格式输出%b	相对应的参数中包含转义字符时,可以使用此替换符进行替换,对应的转义字符会被转义 ?%c	ASCII字符,即显示对应参数的第一个字符%d,%i	十进制整数%o	八进制值%u	不带正负号的十进制值%x	十六进制值(a-f),%X 表示十六进制的A-F%%	表示% 本身常用转义字符\\a	警告字符\\b	后退\\f	换页\\n	换行\\r	回车\\t	水平制表符\\v	垂直制表符\\	\\ 本身

    %#s

    中的# 是数字代表此替换符中的输出字符宽度,不足不空格,默认是右对齐。eg:%-10s 表示10个字符宽,- 表示左对齐

    范例

    #.2f 保留两位小数,且换行输出[root@CentOS8 ~]#printf \"%.2f\\n\" 1 2 31.002.003.00#将文本加()输出[root@CentOS8 ~]#printf \"(%s) \" 1 2 3;echo \'\'(1) (2) (3)[root@CentOS8 ~]#printf \"(%s)\\n\" 1 2 3(1)(2)(3)[root@CentOS8 ~]#printf \"%s %s\\n\" 1 2 3 41 23 4[root@CentOS8 ~]#printf \"%s %s %s\\n\" 1 2 3 41 2 34#制表,表格形式输出[root@CentOS8 ~]#printf \"%-10s %-10s %-4s %s \\n\" 姓名 性别 年龄 体重 小明 男 20 70 小花 女 19 50姓名     性别     年龄 体重小明     男        20   70小花     女        19   50#变量加引号和不加引号的区别#不加引号,将变量中的内容视为一个个的独立字符串[root@CentOS8 ~]#VAR=\"what is it?\";printf \"\\033[1;31m%s\\033[0m\\n\" $VARwhatisit?#加引号,将变量中的内容视为整体[root@CentOS8 ~]#VAR=\"what is it?\";printf \"\\033[1;31m%s\\033[0m\\n\" \"$VAR\"what is it?

    运算符

    算术运算符

    shell 允许在某些情况下对算术表达式进行求值,如:let 和declare 内置命令, (( )) 复合命令和算术扩展。求值以固定宽度的整数进行,不检查溢出,尽管除以0 并不被标记为错误?运算符及其优先级,关联性和C 语言相同。

    注意:bash 只支持整数,不支持小数。且乘法符号在某些场景需转义

    + - * / %	加,减,乘,除,取模i++ i--	先使用变量,再加1++i --i	先加1,再使用变量**	乘方<< >>	左移位 右移位+= -= *= /= %= <<= >>= &= ^= |=  增强型赋值 eg: a+=2 等同于 a=a+2,其他类似! ~	 非- +	正负值<= >= < > == != 比较运算符&	位与|	位或^	位异或&&	逻辑与||	逻辑或expr?expr:expr	三元表达式 ? 左边的expr是表达式,右边的expr是表达式为true 的值,: 后接的expr 是表达式为false 的值

    实现算术运算

    let var=算术表达式((var=算术表达式))var=$[算术表达式]var=$((算术表达式))var=$(expr arg1 arg2...)declare -i var = 数值echo \'算术表达式\' | bc

    范例

    [root@CentOS8 ~]#i=10[root@CentOS8 ~]#let i+=20[root@CentOS8 ~]#echo $i30[root@CentOS8 ~]#j=20[root@CentOS8 ~]#let i*=j[root@CentOS8 ~]#echo $i600[root@CentOS8 ~]#unset i j;[root@CentOS8 ~]#i=10[root@CentOS8 ~]#j=20[root@CentOS8 ~]#declare -i result=i*j[root@CentOS8 ~]#echo $result200[root@CentOS8 ~]#echo \"scale=3;20/3\" | bc6.666#自增,i++和++i 的区别[root@CentOS8 ~]#unset i j;i=1;let j=i++;echo \"i=$i,j=$j\"i=2,j=1[root@CentOS8 ~]#unset i j;i=1;let j=++i;echo \"i=$i,j=$j\"i=2,j=2

    范例 – 雉兔同笼

    [root@CentOS8 script]#vim chook_rabbit.sh1 #!/bin/bash2 #********************************************************************3 # Author:dawn4 # Date:2020-08-08 15:38:195 # FileName:chook_rabbit.sh6 # URL:https://blog.csdn.net/xiao_dan_7 # Version:1.08 # Description:The test script9 #********************************************************************10 HEAD=$111 FOOT=$21213 RABBIT=$(((FOOT-HEAD-HEAD)/2))14 CHOOK=$[HEAD-RABBIT]15 echo RABBIT:$RABBIT16 echo CHOOK:$CHOOK[root@CentOS8 script]#bash chook_rabbit.sh 30 80RABBIT:10CHOOK:20

    逻辑运算符

    true,false

    1,真0,假

    & 位与,和0相与,结果为0,和1相与,结果保留原值

    1 & 1 = 11 & 0 = 00 & 1 = 00 & 0 = 0

    | 位或,和1相或结果为1, 和0相或,结果保留原值

    1 | 1 = 11 | 0 = 10 | 1 = 10 | 0 = 0

    !

    !1 = 0	!true!0 = 1 	!false

    ^ 异或

    异或的两个值,相同为假,不同为真。两个数字X,Y异或得到结果Z,Z再和任意两者之一X异或,将得出另一个值Y

    1 ^ 1 = 01 ^ 0 = 10 ^ 1 = 10 ^ 0 = 0

    范例

    #异或用于两个值之间的交换[root@CentOS8 script]#x=10;y=20;temp=$x;x=$y;y=$temp;echo x=$x,y=$yx=20,y=10[root@CentOS8 script]#x=10;y=20;x=$[x^y];y=$[x^y];x=$[x^y];echo x=$x,y=$yx=20,y=10

    短路运算

    && 短路与

    CMD1 短路与 CMD2第一个CMD1 结果为真(1), 第二个CMD2 必须参与运算,才能得到最终的结果第一个CMD1 结果为假(0),总的结果必定为0,因此不需要执行CMD2

    || 短路或

    CMD1 短路或 CMD2第一个CMD1 结果为真(1),总的结果必定为1,因此不需要执行CMD2第一个CMD1 结果为假(0),第二个CMD2 必须参与运算,才能得到最终的结果

    关系运算符

    关系运算符只支持数字,不支持字符串,除非字符串的值是数字

    -eq		检测两个数是否相等,相等返回true-ne		检测两个数是否不想等,不想等返回true-gt		是否大于,是返回true-ge		是否大于等于与,是返回true-lt 	是否小于,是返回true-le		是否小于等于,是返回true

    范例

    [root@CentOS8 script]#i=10[root@CentOS8 script]#j=8[root@CentOS8 script]#[ $i -lt $j ][root@CentOS8 script]#echo $?1[root@CentOS8 script]#[ i -gt j ]-bash: [: i: integer expression expected

    条件测试命令

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

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

    数值测试

    test EXPRESSION[ EXPRESSION ]  和test等价,建议使用[][[ EXPRESSION ]]ps:EXPRESSION 前后必须有空白字符#判断NAME 变量是否定义[ -v NAME ]#判断NAME 变量是否定义且是名称引用[ -R NAME ]

    范例

    [root@CentOS8 script]#unset x[root@CentOS8 script]#test -v x[root@CentOS8 script]#echo $?1#[  ] 内部必须有空格,否则无效[root@CentOS8 script]#[-v y]-bash: [-v: command not found[root@CentOS8 script]#[ -v y ][root@CentOS8 script]#echo $?0

    字符串测试

    test和[  ] 用法-z STRING	字符串是否为空,没定义或空则为真,不空为假-n STRING	字符串是否不空,不空则为真,空为假STRING	等同于 -n STRING[[ expression ]]用法== 左侧字符串是否和右侧的PATTERN相同此表达式用于[[  ]]中,PATTERN 为通配符=~ 左侧字符串是否能够被右侧的正则表达式的PATTERN所匹配此表达式用于[[ ]]中,扩展的正则表达式

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

    范例- [] 的使用

    [root@CentOS8 script]#[ \"$NAME\" ][root@CentOS8 script]#echo $?1#比较字符串时,建议变量放在\"\" 中[root@CentOS8 script]#NAME=\"I love linux\"[root@CentOS8 script]#[ $NAME ]-bash: [: love: binary operator expected[root@CentOS8 script]#[ \"$NAME\" ][root@CentOS8 script]#echo $?0#比较字符串时,建议变量放在\"\" 中[root@CentOS8 script]#[ \"I love shell\" ][root@CentOS8 script]#echo $?0[root@CentOS8 script]#[ I love bash ]-bash: [: love: binary operator expected[root@CentOS8 script]#FILE=\"a*\"[root@CentOS8 script]#echo $FILEargs.sh a.sh[root@CentOS8 script]#echo \"$FILE\"a*

    范例-[[]] 和通配符

    [root@CentOS8 script]#FILE=\"ab\"[root@CentOS8 script]#[[ $FILE == a* ]][root@CentOS8 script]#echo $?0#加引号[root@CentOS8 script]#FILE=\"a*\"[root@CentOS8 script]#[[ $FILE == a\"*\" ]][root@CentOS8 script]#echo $?0#不想使用通配符*,而是想要表达*本身,可用\"\"引起来或者使用转义[root@CentOS8 script]#FILE=\"ab\"[root@CentOS8 script]#[[ $FILE == a\"*\" ]][root@CentOS8 script]#echo $?1[root@CentOS8 script]#[[ $FILE == a\\* ]][root@CentOS8 script]#echo $?1

    范例-[[]] 和正则表达式

    #判断文件后缀#方式1 通配符[root@CentOS8 ~]#FILE=test.txt[root@CentOS8 ~]#[[ \"$FILE\" == *.log ]][root@CentOS8 ~]#echo $?1#方式2 正则表达式[root@CentOS8 ~]#[[ \"$FILE\" =~ \\.log$ ]][root@CentOS8 ~]#echo $?1[root@CentOS8 ~]#FILE=test.log[root@CentOS8 ~]#[[ \"$FILE\" =~ \\.log$ ]][root@CentOS8 ~]#echo $?0

    文件测试

    存在性测试

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

    文件权限测试

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

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

    文件属性测试

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

    组合测试

    方式一 []

    [ expre1 -a expre2 ]	且,expre1 和expre2 都为真,结果为真[ expre1 -o expre2 ]	或,expre1 和expre2 任意一个为真,结果为真[ ! expre ]		取反

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

    范例

    [root@CentOS8 ~]#ll /data/scripts/test.sh-rw-r--r-- 1 root root 0 Aug 11 10:03 /data/scripts/test.sh[root@CentOS8 ~]#FILE=\"/data/scripts/test.sh\"[root@CentOS8 ~]#[ -f $FILE -a -x $FILE ][root@CentOS8 ~]#echo $?1[root@CentOS8 ~]#[ -f $FILE -o -x $FILE ][root@CentOS8 ~]#echo $?0[root@CentOS8 ~]#[ ! -x $FILE ][root@CentOS8 ~]#echo $?0

    方式二 && 和 ||

    cmd1 && cmd2	且,短路与,表示条件性的and then如果cmd1 执行成功,将执行cmd2,否则,不执行cmd2cmd1 || cmd2	或,短路或,表示条件性的or else如果cmd1 执行成功,不执行cmd2,否则,将执行cmd2!cmd	非,取反

    范例

    [root@CentOS8 ~]#[ \"A\" = \"B\" ] && echo \"String are equal\"[root@CentOS8 ~]#[ \"A\" != \"B\" ] && echo \"String are equal\"String are equal[root@CentOS8 ~]#id haha &> /dev/null || useradd haha[root@CentOS8 ~]#getent passwd hahahaha:x:1001:1001::/home/haha:/bin/bash#&& 和|| 组合使用[root@CentOS8 ~]#name=dawn;id $name &> /dev/null && echo \"$name is exist\"dawn is exist[root@CentOS8 ~]#name=haha;id $name &> /dev/null || echo \"$name is not exist\"haha is not exist[root@CentOS8 ~]#name=dawn;id $name &> /dev/null && echo \"$name is exist\" || echo \"$name is not exist\"dawn is exist[root@CentOS8 ~]#name=dawn;id $name &> /dev/null || echo \"$name is exist\" && echo \"$name is not exist\"dawn is not exist[root@CentOS8 ~]#name=haha;id $name &> /dev/null || echo \"$name is exist\" && echo \"$name is not exist\"haha is existhaha is not exist[root@CentOS8 ~]#name=haha;id $name &> /dev/null && echo \"$name is exist\" || echo \"$name is not exist\"haha is not exist#总结:如果&& 和|| 混合使用,&& 要在前,|| 放在后

    接受输入 read

    使用 read 接收输入的值,将输入值分配给你一个或多个shell 变量。

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

    格式

    read [options]...[name...]#常见参数说明-p	指定要输入内容的提示-s	静默输入,常用于密码-n N	N 为数字,用于指定输入的字符长度N-d \'字符\'		输入结束符-t N	N为数字,用于设置多少秒没有输入动作,则结束输入

    范例

    [root@CentOS8 scripts]#readdawn[root@CentOS8 scripts]#echo $REPLYdawn[root@CentOS8 scripts]#read -p \"Please input your name: \" NAMEPlease input your name: dawn[root@CentOS8 scripts]#echo $NAMEdawn# 面试题:read 和输入重定向[root@CentOS8 scripts]#read i j < test.txt ; echo i=$i j=$ji=1 j=2[root@CentOS8 scripts]#echo 1 2 |read x y;echo x=$x y=$yx= y=[root@CentOS8 scripts]#echo 1 2 |( read x y;echo x=$x y=$y; )x=1 y=2[root@CentOS8 scripts]#echo 1 2 |{ read x y;echo x=$x y=$y; }x=1 y=2
    赞(0) 打赏
    未经允许不得转载:爱站程序员基地 » shell 脚本 – 格式化输出、运算符以及read输入