紧接上文
expr命令
expr
命令用于求表达式的值,格式为:
expr 表达式
表达式说明:
- 用空格隔开每一项
- 用反斜杠放在shell特定的字符前面(发现表达式运行错误时,可以试试转义)
- 对包含空格和其他特殊字符的字符串要用引号括起来
expr
会在stdout
中输出结果。- 如果为逻辑关系表达式,则结果为真,stdout为1,否则为0。
- expr的exit code:
- 如果为逻辑关系表达式,则结果为真,
exit code
为0
,否则为1
。
- 如果为逻辑关系表达式,则结果为真,
字符串表达式
length STRING
返回STRING的长度index STRING CHARSET
CHARSET
中任意单个字符在STRING
中最前面的字符位置,下标从====开始。如果在STRING
中完全不存在CHARSET
中的字符,则返回。substr STRING POSITION LENGTH
返回STRING
字符串中从POSITION
开始,长度最大为LENGTH
的子串。如果POSITION
或LENGTH
为负数,0或非数值,则返回空字符串。下标从====开始
1 | str="Hello World!" |
整数表达式
expr支持普通的算术操作,算术表达式优先级低于字符串表达式,高于逻辑关系表达式。
-
加减运算。两端参数会转换为整数,如果转换失败则报错。
-
乘,除,取模运算。两端参数会转换为整数,如果转换失败则报错。
-
$() $可以改变优先级,但需要用反斜杠转义
1 | a=3 |
可以先正常写表达式最后在补上空格还有反斜杠
逻辑关系表达式
空或为假的,其他为真,遵循短路原则,一旦确定则返回前面的值
如果第一个参数非空且非,则返回第一个参数的值,否则返回第二个参数的值,但要求第二个参数的值也是非空或非,否则返回。如果第一个参数是非空或非时,不会计算第二个参数。
如果两个参数都非空且非0,则返回第一个参数,否则返回0。如果第一个参为0或为空,则不会计算第二个参数。< <= = == != >= >
比较两端的参数,如果为true,则返回1,否则返回0。”==”
是”=”
的同义词。”expr”
首先尝试将两端参数转换为整数,并做算术比较,如果转换失败,则按字符集排序规则做字符比较。- 可以改变优先级,但需要用反斜杠转义
1 | a=3 |
test命令与判断符号[]
逻辑运算符&&和||
-
&& 表示与,|| 表示或
-
二者具有短路原则:
-
expr1 && expr2
:当expr1
为假时,直接忽略expr2
-
expr1 || expr2
:当expr1
为真时,直接忽略expr2
-
-
表达式的
exit code
为0,表示真;为非零,表示假。(与C/C++中的定义相反)表示程序正常返回了 非0表示程序非正常返回了
test命令
在命令行中输入man test
,可以查看test
命令的用法。
-
test
命令用于判断文件类型,以及对变量做比较。 -
test命令用
exit code
返回结果,而不是使用stdout
。0表示真,非0表示假。
stdout
就是程序运行中打印的内容(也就是echo
的内容)`command`或者
$(command)
会将命令中echo
的内容截取下来变成一个字符串后返回
例如:
1 | test 2 -lt 3 # 为真,返回值为0 |
文件类型判断
命令格式
命令格式:test -e filename # 判断文件是否存在
测试参数 | 代表意义 |
---|---|
-e |
文件是否存在 |
-f |
是否为文件 |
-d |
是否为目录 |
文件权限判断
命令格式:test -r filename # 判断文件是否可读
测试参数 | 代表意义 |
---|---|
-r |
文件是否可读 |
-w |
文件是否可写 |
-x |
文件是否可执行 |
-s |
是否为非空文件 |
整数间的比较
命令格式:test $a -eq $b # a是否等于b
测试参数 | 代表意义 |
---|---|
-eq |
a是否等于b |
-ne |
a是否不等于b |
-gt |
a是否大于b |
-lt |
a是否小于b |
-ge |
a是否大于等于b |
-le |
a是否小于等于b |
-eq
:equal (相等) -ne
:not equal (不等)
-gt
:greater than (大于) -ge
:greater than or equal (大于或等于)
-lt
:less than (小于) -le
:less than or equal (小于或等于)
字符串比较
测试参数 | 代表意义 |
---|---|
test -z STRING |
判断STRING是否为空,如果为空,则返回0(exit code) |
test -n STRING |
判断STRING是否非空,如果非空,则返回true(-n可以省略) |
test str1 == str2 |
判断str1是否等于str2 |
test str1 != str2 |
判断str1是否不等于str2 |
多重条件判定
命令格式:test -r filename -a -x filename
测试参数 | 代表意义 |
---|---|
-a |
两条件是否同时成立 |
-o |
两条件是否至少一个成立 |
-! |
取反。如 test ! -x file,当file不可执行时,返回true |
判断符号[]
[]
与test
用法几乎一模一样,更常用于if
语句中。另外[[]]
是[]
的加强版,支持的特性更多。
1 | [ 2 -lt 3 ] # 为真,返回值为0 |
1 | ls # 列出当前目录下的所有文件 |
注意:
[]
内的每一项都要用空格隔开- 中括号内的变量,最好用双引号括起来
- 中括号内的常数,最好用单或双引号括起来
例如:
1 | name="acwing brown" |
== !=
可以直接使用 应该是当成字符串比较
> <
需要加一个\
>= <=
好像不能使用
判断语句
if…then
形式,类似于C/C++
中的if-else
语句。
单层if
命令格式:
1 | if condition |
示例
1 | a=3 |
结果: 3在范围内
单层if-else
命令格式
1 | if condition |
示例
1 | a=3 |
结果: 3小于4
多层if-elif-elif-else
1 | if condition |
示例
1 | a=4 |
结果: 其他
case…esac
形式
类似于C/C++
中的switch
语句。
命令格式
1 | case $变量名称 in |
示例
1 | a=4 |
结果:其他
循环语句
for…in…do…done
格式
1 | for var in val1 val2 val3 |
示例1,输出a 2 cc
,每个元素一行
1 | for i in a 2 cc |
示例2,输出当前路径下的所有文件名,每个文件名一行:
1 | for file in `ls` |
示例3,输出1-10
1 | for i in $(seq 1 10) |
示例4,使用{1..10}
或者{a..z}
也支持倒序
1 | for i in {a..z} |
for ((…;…;…)) do…done
注意是两个括号
命令格式
1 | for ((expression;condition;expression)) |
示例,输出1-10,每个数占一行:
1 | for ((i=1;i<=10;i++)) |
while…do…done
循环
命令格式:
示例
1 | while condition |
示例,文件结束符为Ctrl+d
,输入文件结束符后read
指令返回false
。
1 | while read name |
until…do…done
循环
当条件为真时结束。
这个和上面那个判断恰好相反 上面是判断是真就运行 这个是判断是假就结束
不要把他当成c++的do..while
记
命令格式:
1 | until condition |
示例,当用户输入yes或者YES时结束,否则一直等待读入。
1 | until [ "${word}" == "yes" ] || [ "${word}" == "YES" ] |
break命令
跳出当前一层循环,注意与C/C++不同的是:break不能跳出case语句。他只能跳出循环
shell
中的;;
和c/c++
中的break
在case
语句中类似的
如果在case
语句中添加break
且外层没用循环就会提醒
break: only meaningful in a ˋforˋ, ˋwhileˋ,or ˋuntilˋ loop
示例
1 | while read num |
结果:只要输入的不是0 就打印1~10
case结束 如果输入的是0
则打印 while结束
continue命令
跳出当前循环。
示例:
1 | for ((i=1;i<=10;i++)) |
程序输出1-10中的所有奇数。
死循环的处理方式
如果可以打开该程序,则输入Ctrl+c即可。
否则可以直接关闭进程:
使用top
命令找到进程的PID
输入kill -9 PID
即可关掉此进程
ps aux
返回当前打开的所有进程
函数
bash
中的函数类似于C/C++
中的函数,但return
的返回值与C/C++
不同,返回的是exit code
,取值为0-255
,0
表示正常结束。 没有return
默认返回的是0
如果想获取函数的输出结果,可以通过echo
输出到stdout
中,然后通过$(function_name)
来获取stdout
中的结果。
函数的return
值可以通过$?
来获取。
函数中最后stdout
每条echo
中间用一个空格隔开,无论是否换行是否有\n
通通一个空格
命令格式:
1 | [function] func_name() { # function关键字可以省略 |
不获取return
值和stdout
值
1 | func() { |
结果 Hello brown
获取return
值和stdout
值
不写return
时,默认return 0
。
1 | func() { |
结果:
1 | output = Hello yxc |
函数的输入参数
在函数内,$1表示第一个输入参数,$2表示第二个输入参数,依此类推。
注意:函数内的$0仍然是文件名,而不是函数名。
1 | sum() { |
eval
暂时理解为解决嵌套
结果:$0=./test.sh 110
函数内的局部变量
可以在函数内定义局部变量,作用范围仅在当前函数内。
可以在递归函数中定义局部变量。
格式 local 变量名=变量值
1 | ! /bin/bash |
结果
1 | brown |
第一行为函数内的name
变量,第二行为函数外调用name变量,会发现此时该变量不存在。