持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第1天,点击查看活动详情
11、Shell test 命令
test是shell内置命令,用来检测某个条件是否成立test通常和if语句一起使用,并且大部分if语句都依赖test,shell test命令的用法有两种:
第一种:
test expression #当test判断expression成立时,退出状态为0,否则为非0值
第二种:
[ expression ] #[ ]和expression的两边都有空格,这个空格是必须的,否则会导致语法错误
#[ ]写法更简洁,使用频率更高
1)数值测试
参数和说明如下:
-eq 等于则为真
-ne 不等于则为真
-gt 大于则为真
-ge 大于等于则为真
-lt 小于则为真
-le 小于等于则为真
演示一个参数如下:
num1=200
num2=200
if [ $[num1] -eq $[num2] ]
then
echo '两个数相等!'
else
echo '两个数不相等!'
fi
代码中的 [] 执行基本的算数运算,例如:
a=10
b=10
result=$[a+b] # 注意等号两边不能有空格
echo "result結果为: $result"
2)字符串测试
参数如下:
= 等于则为真
!= 不相等则为真
< 比较两者的大小
> 比较两者的大小
-z 字符串 字符串的长度为零则为真
-n 字符串 字符串的长度不为零则为真
a)比较字符串是否相等:
num1="chuan"
num2="chuan"
if [ $num1 = $num2 ]
then
echo '两个字符串相等!'
else
echo '两个字符串不相等!'
fi
b)比较字符串的大小:
- 字符串大小的比较遵循字典顺序,规则如下:
- 1.如果第一个字符串是第二个字符串的前缀,那么第一个小(比如a小于about)
- 2.从字符串的开头比较,按照字母顺序,a比b小(比如about小于ball)
- 3.如果第一个字符相同,再比较第二个(比如about小于above)
方法:
[ str1 < str2 ]
[ str1 > str2 ]
c)比较字符串的长度
- 没有被定义的字符串长度默认为0
方法:
[ -n str1 ] #检查str1的长度是否非0
[ -z str1 ] #检查str1的长度是否为0
3)文件测试
参数:
-e 文件名 如果文件存在则为真
-r 文件名 如果文件存在且可读则为真
-w 文件名 如果文件存在且可写则为真
-x 文件名 如果文件存在且可执行则为真
-s 文件名 如果文件存在且至少有一个字符则为真
-d 文件名 如果文件存在且为目录则为真
-f 文件名 如果文件存在且为普通文件则为真
-c 文件名 如果文件存在且为字符型特殊文件则为真
-b 文件名 如果文件存在且为块特殊文件则为真
-O file 检查file是否存在并属当前用户所有
-G file 检查file是否存在并且默认组与当前用户相同
file1 -nt file2 检查file1是否比file2新
file1 -ot file2 检查file1是否比file2旧
举一个例子:
if [ -e ./test1.sh ]
then
echo '文件已存在!'
else
echo '文件不存在!'
fi
12、shell 控制流
1)if判断流
if else fi 语法格式如下:
if condition
then
command1
command2
...
commandN
fi
测试1:
a=5
b=6
if [ $a -gt $b ]
then
echo '大于'
else
echo '小于'
fi
测试2:
a=5
b=6
if [ $a==$b ]
then
echo '等於'
elif [ $a -gt $b ]
then
echo "a 大于 b"
elif [ $a -lt $b ]
then
echo "a 小于 b"
else
echo "没有符合的条件"
fi
2)for 循环
- 1.for循环在实际生成中应用非常多,避免人工重复的去操作某个事情
- 2.for循环中的列表支持正则表达式
- 3.for循环中使用(()),双括号内支持C语言的命令
- 4.for循环中的变量,只是循环去取值列表中取值,然后进行do操作,所以取值列表中的参数个数,决定了循环的次数
语法:
for var in item1 item2 ... itemN
do
command1
command2
...
commandN
done
测试1:顺序输出当前列表中的数字
for a in 1 2 3 4 5
do
echo "值依次爲: $a"
done
测试2:顺序输出字符串中的字符
for str in hello chuan chuan
do
echo $str
done
测试3:打印任意数的乘法表
echo "输入一个数:"
read num
for (( i=1;i<=$num;i++ ))
do
for (( j=1;j<=$num;j++ ))
do
[ $j -le $i ] && echo -n "${i}*${j}=$((i*j)) " #判断j是否小于i,当
j大于i时不输出,输出不换行,末尾加一个制表符
done
echo "" #输出一个换行符
done
3)while循环
语法格式:
while condition
do
command
done
测试1,依次输出1到6:
int=1
while(( $int<=6 ))
do
echo $int
let "int++"
done
4)until 循环
until 循环执行一系列命令直至条件为 true 时停止。until 循环与 while 循环在处理方式上刚好相反。 语法为:
until condition
do
command
done
举个例子:使用 until 命令来输出 0 ~ 6 的数字
a=0
until [ ! $a -lt 6 ]
do
echo $a
a=`expr $a + 1`
done
5)case ... esac
case ... esac 为多选择语句,与C语言中的 switch ... case 类似,每个 case 分支用右圆括号开始,用两个分号 ;; 表示 break,即执行结束. 语法为:
case 值 in
模式1)
command1
command2
...
commandN
;;
模式2)
command1
command2
...
commandN
;;
esac
测试:提示输入 1 到 4,与每一种模式进行匹配
echo '输入 1 到 4 之间的数字:'
echo '你输入的数字为:'
read a
case $a in
1) echo '你选择了 1'
;;
2) echo '你选择了 2'
;;
3) echo '你选择了 3'
;;
4) echo '你选择了 4'
;;
*) echo '你没有输入 1 到 4 之间的数字'
;;
esac
6)跳出循环
break break命令允许跳出所有循环(终止执行后面的所有循环)。
continue continue命令与break命令类似,只有一点差别,它不会跳出所有循环,仅仅跳出当前循环。
注:所有语言这个都是通用的,就不多说了。
13、Shell 函数
直接来看一个demo函数:
demoFun(){
echo "測試一下我的函數!"
}
echo "函数开始执行"
demoFun
echo "-函数执行完毕"
定义一个带有return语句的函数: 代码为:
add(){
echo "这个函数为求两个函数之和.."
echo "输入第一个数字: "
read aNum
echo "输入第二个数字: "
read bNum
echo "两个数字分别为 $aNum 和 $bNum !"
return $(($aNum+$bNum))
}
add
echo "输入的两个数字之和为 $? !"
引: Shell脚本中?、!、$$、*、#、@等的意义说明?
$$
Shell本身的PID(ProcessID,即脚本运行的当前 进程ID号)
$!
Shell最后运行的后台Process的PID(后台运行的最后一个进程的 进程ID号)
$?
最后运行的命令的结束代码(返回值)即执行上一个指令的返回值 (显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误)
$-
显示shell使用的当前选项,与set命令功能相同
$*
所有参数列表。如"$*"用「"」括起来的情况、以"$1 $2 … $n"的形式输出所有参数,此选项参数可超过9个。
$@
所有参数列表。如"$@"用「"」括起来的情况、以"$1" "$2" … "$n" 的形式输出所有参数。
$@ 跟$*类似,但是可以当作数组用
$#
添加到Shell的参数个数
$0
Shell本身的文件名
$1~$n
添加到Shell的各参数值。$1是第1参数、$2是第2参数…。
测试脚本
#!/bin/sh
echo "number:$#"
echo "scname:$0"
echo "first :$1"
echo "second:$2"
echo "argume:$@"
结果:
number:2
scname:./variable
first: aa
second:bb
argume:aa bb
14、Shell 输入/输出重定向
相关参数如下:
command > file 将输出重定向到 file。
command < file 将输入重定向到 file。
command >> file 将输出以追加的方式重定向到 file。
n > file 将文件描述符为 n 的文件重定向到 file。
n >> file 将文件描述符为 n 的文件以追加的方式重定向到 file。
n >& m 将输出文件 m 和 n 合并。
n <& m 将输入文件 m 和 n 合并。
<< tag 将开始标记 tag 和结束标记 tag 之间的内容作为输入。
1)输出重定向
将输出重定向到wen文件夹:
这样的重定向有一个缺点就是会覆盖原来的内容,如果你不想覆盖原来的内容,你可以使用:
command >> file 将输出以追加的方式重定向到 file。
2)输入重定向
和输出重定向一样,Unix 命令也可以从文件获取输入,语法为:
command1 < file1
这样,本来需要从键盘获取输入的命令会转移到文件读取内容。
注意:输出重定向是大于号(>),输入重定向是小于号(<)。
users 文件:
菜鸟教程:www.runoob.com
菜鸟教程:www.runoob.com
接着以上实例,我们需要统计 users 文件的行数,执行以下命令:
$ wc -l users
2 users
也可以将输入重定向到 users 文件:
wc -l < users
2
注意:上面两个例子的结果不同:第一个例子,会输出文件名;第二个不会,因为它仅仅知道从标准输入读取内容。
引入:同时替换输入和输出,执行command1,从文件infile读取内容,然后将输出写入到outfile中。
command1 < infile > outfile
3)重定向深入讲解
一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件:
- 标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。
- 标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。
- 标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。
默认情况下,command > file 将 stdout 重定向到 file,command < file 将stdin 重定向到 file。
如果希望 stderr 重定向到 file,可以这样写:
$ command 2>file
2 表示标准错误文件(stderr)。
如果希望将 stdout 和 stderr 合并后重定向到 file,可以这样写:
$ command > file 2>&1
或者
$ command >> file 2>&1
4)Here Document(了解)
Here Document 是 Shell 中的一种特殊的重定向方式,用来将输入重定向到一个交互式 Shell 脚本或程序。 语法为;
command << delimiter
document
delimiter
它的作用是将两个 delimiter 之间的内容(document) 作为输入传递给 command。
注意:
- 结尾的delimiter 一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和 tab 缩进。
- 开始的delimiter前后的空格会被忽略掉。
在命令行中通过 wc -l 命令计算 Here Document 的行数:
$ wc -l << EOF
欢迎来到
菜鸟教程
www.runoob.com
EOF
3 # 输出结果为 3 行
$
我们也可以将 Here Document 用在脚本中,例如:
#!/bin/bash
# author:菜鸟教程
# url:www.runoob.com
cat << EOF
欢迎来到
菜鸟教程
www.runoob.com
EOF
执行以上脚本,输出结果:
欢迎来到
菜鸟教程
www.runoob.com
5)/dev/null 文件
如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null,/dev/null 是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到。但是 /dev/null 文件非常有用,将命令的输出重定向到它,会起到"禁止输出"的效果。
如果希望屏蔽 stdout 和 stderr,可以这样写:
$ command > /dev/null 2>&1
注意: 0 是标准输入(STDIN),1 是标准输出(STDOUT),2 是标准错误输出(STDERR)。
这里的 2 和 > 之间不可以有空格,2> 是一体的时候才表示错误输出。