shell 脚本 - 格式化输出、运算符以及read输入
格式化输出、运算符以及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 3 1.00 2.00 3.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 4 1 2 3 4 [root@CentOS8 ~]#printf "%s %s %s\n" 1 2 3 4 1 2 3 4 #制表,表格形式输出 [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" $VAR what is it? #加引号,将变量中的内容视为整体 [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 $i 30 [root@CentOS8 ~]#j=20 [root@CentOS8 ~]#let i*=j [root@CentOS8 ~]#echo $i 600 [root@CentOS8 ~]#unset i j; [root@CentOS8 ~]#i=10 [root@CentOS8 ~]#j=20 [root@CentOS8 ~]#declare -i result=i*j [root@CentOS8 ~]#echo $result 200 [root@CentOS8 ~]#echo "scale=3;20/3" | bc 6.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.sh 1 #!/bin/bash 2 #******************************************************************** 3 # Author:dawn 4 # Date:2020-08-08 15:38:19 5 # FileName:chook_rabbit.sh 6 # URL:https://blog.csdn.net/xiao_dan_ 7 # Version:1.0 8 # Description:The test script 9 #******************************************************************** 10 HEAD=$1 11 FOOT=$2 12 13 RABBIT=$(((FOOT-HEAD-HEAD)/2)) 14 CHOOK=$[HEAD-RABBIT] 15 echo RABBIT:$RABBIT 16 echo CHOOK:$CHOOK [root@CentOS8 script]#bash chook_rabbit.sh 30 80 RABBIT:10 CHOOK:20
逻辑运算符
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
1 ^ 1 = 0 1 ^ 0 = 1 0 ^ 1 = 1 0 ^ 0 = 0
范例
#异或用于两个值之间的交换 [root@CentOS8 script]#x=10;y=20;temp=$x;x=$y;y=$temp;echo x=$x,y=$y x=20,y=10 [root@CentOS8 script]#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 必须参与运算,才能得到最终的结果
关系运算符
关系运算符只支持数字,不支持字符串,除非字符串的值是数字
-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 $FILE args.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,否则,不执行cmd2 cmd1 || 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 haha haha: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 exist haha 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]#read dawn [root@CentOS8 scripts]#echo $REPLY dawn [root@CentOS8 scripts]#read -p "Please input your name: " NAME Please input your name: dawn [root@CentOS8 scripts]#echo $NAME dawn # 面试题:read 和输入重定向 [root@CentOS8 scripts]#read i j < test.txt ; echo i=$i j=$j i=1 j=2 [root@CentOS8 scripts]#echo 1 2 |read x y;echo x=$x y=$y x= 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
- Oralce SQLPlus 以及shell脚本中spool输出到文件时的格式化输出
- Oralce SQLPlus 以及shell脚本中spool输出到文件时的格式化输出
- Oralce SQLPlus 以及shell脚本中spool输出到文件时的格式化输出
- shell脚本之重定向、标准输入、输出、错误输出的使用
- shell基础五:输入和输出(echo,read,cat,管道,tee,重定向等)
- shell基础:使用read、命令行脚本传参实现输入2个整数并计算
- LINUX下用SHELL脚本执行带输入输出参数的ORACLE存储过程并得到结果
- shell 脚本格式化输出
- 从输入/输出的视角看TCP/IP(终端,shell以及X Window)
- shell脚本编程设计——根据输入的数输出菱形、三角形或者数字金字塔(带闪烁颜色)
- Shell 脚本-4-输入输出
- linux shell 编程笔记 - shell的输入与输出 -2- read - cat - 管道
- 作业《IOS_C语言》进制,C数据类型,常量类型,运算符,表达式,格式化输入输出
- ssh、scp的使用,以及shell脚本解决scp需要输入密码的问题
- shell 输入输出脚本
- shell脚本--输入与输出
- Shell编程中的用户输入处理(4):在shell脚本中,使用read命令获取命令行输入
- C语言---程序的一般形式、数据类型、常量变量、运算符、表达式、格式化输入输出
- shell 脚本格式化输出
- shell read脚本输出参数