LV060-语句
本文主要是 shell——运算符和语句相关笔记,若笔记中有错误或者不合适的地方,欢迎批评指正 😃。
一、说明性语句
其实就是注释,以 # 号开始到该行结束,不被解释执行。 sh 里没有多行注释,只能每一行加一个#号。
#--------------------------------------------
# 这是一个注释
# author:
# file name:
# description:
#--------------------------------------------二、功能性语句
1. readonly
readonly Variable # Variable 为变量名称使用 readonly 命令可以 将变量定义为只读变量,只读变量的值不能被改变。
2. unset
unset Variable # Variable 为变量名称该命令可以删除已经定义的变量。
3. read
3.1 使用格式
read 用来从标准输入中读取数据并赋值给变量。如果没有进行重定向,默认就是从键盘读取用户输入的数据;如果进行了重定向,那么可以从文件中读取数据。
read [option] [Variables]| [option] | -a array | 把读取的数据赋值给数组 array,从下标 0 开始 |
| -d delimiter | 用字符串 delimiter 指定读取结束的位置,而不是一个换行符(默认结束符号为换行符,读取到的数据不包括 delimiter)。 | |
| -n num | 读取 num 个字符就结束,而不是整行字符。如果没有读满 num 个字符就按下回车或遇到换行符,则也会结束读取。 | |
| -N num | 严格要求读满 num 个字符才自动结束读取,即使中途按下了回车或遇到了换行符也不结束,其中换行符或回车算一个字符。 | |
| -p prompt | 显示提示信息,提示内容为 prompt。默认不支持 "\n" 换行,要换行需要特殊处理(例如:通过 $'string \n' 就可以实现换行输入) | |
| -t timeout | 设置超时时间,单位为秒。如果用户没有在指定时间内输入完成,那么 read 将会返回一个非 0 的退出状态,表示读取失败,即使已经输入了一部分。 | |
| -u fd | 使用文件描述符 fd 作为输入源,而不是标准输入,类似于重定向。 | |
| -e | 在输入的时候可以使用命令补全功能(Tab 键)。 | |
| -r | 原样读取(Raw mode),不把反斜杠字符解释为转义字符,这意味着 "\" 会变成文本的一部分。 | |
| -s | 静默模式(Silent mode),不会在屏幕上显示输入的字符。可用于输入密码和其它确认信息的时候。 | |
| [Variables] | 变量名称 | |
(1)可以使用多个参数。
(2)变量读取说明
read [-ers] [-a aname] [-d delim] [-i text] [-n num] [-N num] [-p prompt] [-t timeout] [-u fd] [var_name1 var_name2 ...]首先说一下 IFS(internal field separator ,为 内部字段分隔符,是 bash shell 中的环境变量,它定义了 bash shell 用作字段分隔符的一系列字符,默认情况下, bash shell 会将下列字符当做字段分隔符:空格、制表符 和 换行符。
read 命令用于从标准输入中读取输入单行,并将读取的单行根据 IFS 环境变量分裂成多个字段,并将分割后的字段分别赋值给指定的变量列表 var_name 。第一个字段分配给第一个变量 var_name1 ,第二个字段分配给第二个变量 var_name2 ,依次到结束。如果指定的变量名少于字段数量,则多出的字段数量也同样分配给最后一个 var_name ,如果指定的变量命令多于字段数量,则多出的变量赋值为空。如果没有指定任何 var_name ,则分割后的所有字段都存储在环境变量 REPLY 中。
3.2 使用实例
#!/bin/bash
read -p $'Enter your name: \n'
echo $REPLY运行结果:
Enter your name:
qidaink
qidaink(3)给多个变量赋值时,必须在一行内输入所有的值,不能换行,否则只能给第一个变量赋值,后续变量都会赋值失败。
4. test
test 命令用于 检查某个条件是否成立,它可以进行数值、字符和文件三个方面的测试。通常和 if 语句一起使用,并且大部分 if 语句都依赖 test 。
以下只为举例说明使用格式,还有一些运算符可以查看本篇笔记的《运算符》。
4.1 数值测试
test $[num1] <关系运算符> $[num2]| 运算符 | -eq | 等于,则为真 |
| -ne | 不等于,则为真 | |
| -gt | 大于,则为真 | |
| -ge | 大于等于,则为真 | |
| -lt | 小于,则为真 | |
| -le | 小于等于,则为真 |
4.2 字符串测试
test $[num1] <字符串运算符> $[num2]| 运算符 | = | 等于,则为真 |
| != | 不等于,则为真 | |
| -z 字符串 | 字符串的长度为零,则为真 | |
| -n 字符串 | 字符串的长度不为零,则为真 |
4.3 文件测试
test <文件测试运算符> file_name| 运算符 | -e file | 如果文件存在,则为真 |
| -f file | 如果文件存在且可读,则为真 |
5. echo
5.1 使用格式
echo 用于在屏幕上打印出指定的字符串,命令格式如下:
echo [option] string| -n | 禁止在最后自动换行 | |
| -e | 开启转义字符功能,即遇到以下字符进行处理,而不会将其当成一般字符输出 | |
| \a | 警报,响铃 | |
| \b | 退格(删除键) | |
| \f | 换页(FF),将当前位置移到下页开头 | |
| \n | 换行 | |
| \c | 不换行 | |
| \r | 回车 | |
| \t | 水平制表符(tab 键) | |
| \v | 垂直制表符 | |
| \ooo | 插入 ooo(八进制)所代表的 ASCII 字符 | |
| \\ | 反斜杠 | |
| --version | 显示版本信息 | |
| --helo | 显示帮助 | |
5.2 使用实例
5.2.1 显示普通字符串
#!/bin/bash
echo "string1"
echo "string2"
echo string3运行结果:
string1
string2
string35.2.2 显示转义字符
#!/bin/bash
echo "\"string\""
echo \"string\"运行结果:
"string"
"string"5.2.3 显示变量
#!/bin/bash
name=qidaink
echo $name
echo "$name"
echo "${name}"运行结果:
qidaink
qidaink
qidaink5.2.4 显示换行与不换行
#!/bin/bash
name=qidaink
echo -e "$name\nString1" # 开启转义字符,\n 换行
echo "$name\nString1"
echo -e "$name\c" # 开启转义字符,\c 不换行
echo "String2"运行结果:
qidaink
String1
qidaink\nString1
qidainkString25.2.5 显示结果定向至文件
#!/bin/bash
name=qidaink
echo -e "$name\nString1" > file.txt运行结果:会在当前 Shell 脚本所在目录创建一个 filt.txt 文件(无该文件的话),并将要显示的内容显示在 filt.txt 文件中。
5.2.6 原样输出字符串
- 原样输出字符串,不进行转义或取变量(用单引号)
#!/bin/bash
name=qidaink
echo "$name\nString1"
echo '$name\nString1'运行结果:
qidaink\nString1
$name\nString15.2.7 显示命令执行结果
#!/bin/bash
echo date
echo 'date'
echo "date"运行结果:
2022年 02月 14日 星期一 13:29:17 CST
date
date6. printf
6.1 使用格式
printf 由 POSIX 标准所定义,因此使用 printf 的脚本比使用 echo 移植性好。 printf 使用 引用文本或空格分隔 的参数,外面可以在 printf 中使用格式化字符串,还可以制定字符串的宽度、左右对齐方式等。默认的 printf 不会像 echo 自动添加换行符。使用格式如下:
printf "format-string>" [arguments...]其中 format-string 为格式控制字符串, arguments 为参数列表。 Shell 脚本中的 printf 和 C 语言中的 printf 用法基本一致,只是在写法上有些许区别。
- printf 命令不用加括号
- format-string 可以没有引号,但最好加上,单引号双引号均可。
- 参数多于格式控制符( % )时, format-string 可以重用,可以将所有参数都转换。
- arguments 使用 空格分隔,不用逗号。
6.2 转义字符
| \a | 警报,响铃 |
| \b | 退格(删除键) |
| \c | 不显示输出结果中任何结尾的换行字符,而且任何留在参数里的字符、任何接下来的参数以及任何留在格式字符串中的字符都被忽略。 |
| \f | 换页(FF),将当前位置移到下页开头 |
| \n | 换行 |
| \r | 回车 |
| \t | 水平制表符(tab 键) |
| \v | 垂直制表符 |
| \ooo | 插入 ooo(八进制)所代表的 ASCII 字符 |
| \\ | 反斜杠字符 |
6.3 格式控制字符串
6.3.1 格式控制字符
| 格式字符 | 形式 | 意义 |
| i, d | %i, %d | 以十进制形式输出带符号整数(正数不输出符号) |
| u | %u | 以十进制形式输出无符号整数 |
| o | %o | 以八进制形式输出无符号整数(不输出前缀 0) |
| x, X | %x, %X | 以十六进制形式输出无符号整数(不输出前缀 0x) |
| f | %f | 以小数形式输出单、双精度实数 |
| e, E | %e, %E | 以指数形式输出单、双精度实数 |
| g, G | %g, %G | 以 %f 或 %e 中较短的输出宽度输出单、双精度实数 |
| c | %c | 输出单个字符 |
| s | %s | 输出字符串 |
6.3.2 标识
| 标识 | 描述 |
| - | 在给定的字段宽度内左对齐,默认是右对齐 |
| + | 强制在结果之前显示加号或减号(+ 或 -),即正数前面会显示 + 号。默认情况下,只有负数前面会显示一个 - 号。 |
| space (空格) | 有符号值若为正,则在值前显示前导空格(但是不显示符号);若为负,则在值前显示-。 |
| # | 与 o、x 或 X 说明符一起使用时,非零值前面会分别显示 0、0x 或 0X。 |
| 与 e、E 和 f 一起使用时,会强制输出包含一个小数点,即使后边没有数字时也会显示小数点。默认情况下,如果后边没有数字时候,不会显示显示小数点。 | |
| 与 g 或 G 一起使用时,结果与使用 e 或 E 时相同,但是尾部的零不会被移除。 | |
| 0 | 输出数值时指定左面不使用的空位置自动填 0。 |
6.3.3 最小输出宽度( width )
| 宽度 | 描述 |
| number | 数值(十进制整数),数据长度 小于 number,则左补空格;否则按实际输出。 |
| * | 星号,精度在 format 字符串中未指定,但是会作为附加整数值参数放置于要被格式化的参数之前。 |
6.3.4 精度( .precision )
| 精度 | 描述 |
| .number | 对于整数说明符(d、i、o、u、x、X):precision 指定了要写入的数字的最小位数。如果写入的值短于该数,结果会用前导零来填充。如果写入的值长于该数,结果不会被截断。精度为 0 意味着不写入任何字符。 |
| 对于 e、E 和 f 说明符:要在小数点后输出的小数位数。 | |
| 对于 g 和 G 说明符:要输出的最大有效位数。 | |
| 对于 s : 要输出的最大字符数, 不足 number 则正常输出,超过则截断。默认情况下,所有字符都会被输出,直到遇到末尾的空字符。 | |
| 对于 c 类型:没有任何影响。 | |
| 当未指定任何精度时,默认为 1。如果指定时不带有一个显式值,则假定为 0。 | |
| .* | 星号,精度在 format 字符串中未指定,但是会作为附加整数值参数放置于要被格式化的参数之前。 但是在尝试的时候似乎有一些数据类型不匹配的情况,不过也用的不多。 |
6.4 使用实例
#!/bin/bash
printf "%-10s %-8s %-4s\n" name sex kg
printf "%-10s %-8s %-4.1f\n" qidai 男 72.162
printf "%-10s %-8s %-4.1f\n" fanhua 男 60.9612
printf "%-10s %-8s %-4.1f\n" yunyuhai 女 48.96313141三、结构性语句
结构性语句主要根据程序的运行状态、输入数据、变量的取值、控制信号以及运行时间等因素来控制程序的运行流程。主要包括:条件测试语句(两路分支)、多路分支语句、循环语句、循环控制语句和后台执行语句等。
1. 分支语句
1.1 if...else... 语句
1.1.1 使用格式 1
- 语法结构 1
# if ... fi 结构
if [ expression ]
then
Statement(s) to be executed if expression is true
fi
# 或者
if [ expression ] ; then
Statement(s) to be executed if expression is true
fi
# 或者写成一行
if [ expression ] ; then Statement(s) to be executed if expression is true; fi;1.1.2 使用格式 2
- 语法结构 2
# if ... else ... fi 结构
if [ expression ]
then
Statement(s) to be executed if expression is true
else
Statement(s) to be executed if expression is not true
fi1.1.3 使用格式 3
- 语法结构 3
# if ... elif ... fi 结构
if [ expression 1 ]
then
Statement(s) to be executed if expression 1 is true
elif [ expression 2 ]
then
Statement(s) to be executed if expression 2 is true
elif [ expression 3 ]
then
Statement(s) to be executed if expression 3 is true
else
Statement(s) to be executed if no expression is true
f【注意】
(1)以上三种结构中, if 和 elif 之后要跟一个 then ,结束要有 fi ,中间的执行语句不需要像 C 语言 一样有 {} 。
(2) then 可以与 if 或者 elif 写在同一行,但是要加一个 ;
(3) if 也常与 test 命令一起使用。
1.2 case 语句
1.2.1 使用格式
case 值 in
模式1)
command1
command2
command3
;;
模式2)
command1
command2
command3
;;
*)
command1
command2
command3
;;
esac【注意】
(1)取值后面必须为单词 in ,每一模式必须以右括号结束。取值可以为变量或常数,匹配发现取值符合某一模式后,其间所有命令开始执行直至 ;; 。
(2)每个 case 分支用 右圆括号 开始,用两个分号 ;; 表示 break ,即执行结束。如果没有匹配到任何一个模式,使用星号 * 捕获该值,再执行后面的命令。
(3) esac (就是 case 反过来)作为整个结构结束标记。
1.2.2 使用实例
#!/bin/bash
read -p "Inter a number:" value
if [ $value -lt 0 ] || [ $value -gt 100 ]
then
echo "input error."
exit 0
else
value= expr $value / 10
case $value in
8 | 9 | 10)
echo "A"
;;
6 | 7)
echo "B"
;;
*)
echo "C"
;;
esac
fi2. 循环语句
2.1 for 循环
2.1.1 使用格式 1
- 语法结构 1
for 变量 in 列表
do
command1
command2
...
commandN
done2.1.2 使用格式 2
- 语法结构 2
for((表达式1; 表达式2; 表达式2))
do
command1
command2
...
commandN
done【注意】
(1)以上两种结构都可以,但是都要注意不可省略 do 和 done 。
2.1.3 使用实例
#!/bin/bash
printf "\033[31m shell方式 \033[0m\n"
for value in 1 2 3 4 5
do
printf "$value"
done
echo ""
printf "\033[31m 类似C语言方式 \033[0m\n"
for ((val = 1; val <=5; val++))
do
printf "$val"
done
echo ""2.2 while 循环
2.2.1 使用格式 1
- 语法结构 1
while [ expression ]
do
Statement(s) to be executed if expression is true
done2.2.2 使用格式 2
- 语法结构 2
while (( expression ))
do
Statement(s) to be executed if expression is true
done2.2.3 使用实例
#!/bin/bash
# 语法结构 1 例子
i=1
sum=0
while [ $i -le 10 ]
do
sum= expr $sum + $i
i= expr $i + 1
done
echo "i = $i sum = $sum"
# 语法结构 2 例子
num=0
while (( $num < 5))
do
echo "$num"
num= expr $num + 1
done
echo "num=$num"2.3 until 循环
until 循环执行一系列命令直至条件为 true 时停止。 until 循环与 while 循环在处理方式上刚好相反。一般 while 循环优于 until 循环,但在某些时候—也只是极少数情况下, until 循环更加有用。
2.3.1 使用格式
- 语法结构
until [ expression ]
do
Statement(s) to be executed until command is true
done2.3.2 使用实例
#!/bin/bash
num=0
until [ ! ${num} -lt 3 ]
do
echo ${num}
num= expr ${num} + 1
done2.4 无限循环写法
2.4.1 for
# for 写法
for (( ; ; ))
do
command
done2.4.2 while
# while 写法 1
while :
do
command
done
# while 写法 2
while true
do
command
done2.5 跳出循环
2.5.1 使用格式
在循环过程中,有时候需要在未达到循环结束条件时强制跳出循环, Shell 与 C 语言一致,使用两个命令来实现该功能: break 和 continue 。用法与 C 语言一致。
【注意】
(1)一般来说 break 是跳出本层循环, continue 是结束本次循环,直接进入下一次循环。
(2)在嵌套循环中, break 命令后面还可以跟一个整数,表示跳出第几层循环。 continue 后边也可以跟一个整数,表示继续第几层循环。
break n # break 所在循环层为第 1 层,然后再向外计算层数
continue n # continue 所在循环层为第 1 层,然后再向外计算层数2.5.2 使用实例
#!/bin/bash
for var1 in 1 2
do
echo "第1层循环 var1=${var1}"
for var2 in 3 4
do
echo -e "\t第2层循环 var2=${var2}"
for var3 in 5 6
do
if [ ${var1} == 1 ] && [ ${var2} == 4 ] && [ ${var3} == 5 ]
then
echo -e "break 跳出"
break 3
elif [ ${var1} == 1 ] && [ ${var2} == 3 ] && [ ${var3} == 5 ]
then
echo -e "continue 继续"
continue 3
fi
echo -e "\t\t第3层循环 var3=${var3}"
echo -e "\t\t一次循环结束 ${var1} ${var2} ${var3}"
done
done
done四、三目运算符?
1. 使用格式
我也不知道叫啥,其实就很类似于条件语句:
command1 && command2 || command3
command1 && { command2_1; command2_2; command2_3;} || { command3_1; command3_3; command3_3;}2. 使用实例
# fileName 文件不存在,则退出,就可以按照下面方式执行
[ -e $fileName ] || { echo -e "fileName Not existed!"; exit 1; }
#也或者可以增加一些 log 打印信息
[ -e $fileName ] && echo -e "$fileName existed" || { echo -e "$fileName Not existed!"; exit 1; }
#多个命令集合的组合
[ -e $fileName ] && echo -e "$fileName existed"; ehco -e "Other Necessary Information" || { echo -e "$fileName Not existed!"; exit 1; }
[ -e $fileName ] && { echo -e "$fileName existed"; ehco -e "Other Necessary Information"; } || { echo -e "$fileName Not existed!"; exit 1; }
#读取 IP 地址,若为空,则使用默认 IP,否则使用新的 IP 地址
read -p "Please input Management IP (Default is $DEFAULT_IP): " MGMT_IP
[[ -z $MGMT_IP ]] && { MGMT_IP=$DEFAULT_IP; echo -e "Using default IP $MGMT_IP\n" ;} || DEFAULT_IP=$MGMT_IP