最近开始系统学习shell脚本的相关知识,为了对已经学习的知识及时巩固,也为别人提供参考的资料,这里会对自己的学习过程做详细的记录。
本次主要介绍shell脚本的相关概念和基本操作。
1. 创建和运行shell脚本
一般使用vi或者vim来创建并编辑一个shell脚本,如输入vi test1.sh创建一个test1.sh的脚本并等待输入。shell脚本以井号(#)为注释符号,但是shell脚本的第一行一般会在井号后面加上感叹号(#!)的形式来指定这个shell脚本会以用哪一种shell来运行这个脚本,因为可以运行shell的是有很多的。比如在test1.sh的第一行写上#!/bin/bash就是以/bin/bash这个可执行文件来加载test1.sh这个脚本。test1.sh脚本如下
#!/bin/bash
#This is first script to print hello world
echo "hello world"
好了!现在第一个脚本已经准备好了,那么运行一下它。运行之前,要给这个文件一个可执行权限。输入:
chmod u+x test1.sh
现在脚本有可执行权限了,可以运行了,输入:
./test1.sh
运行后会输出:
hello world
注意上面的echo指令在hello world前后加了双引号,其实不加或者加上单引号’hello world’也可以。但是当字符串本身就有单引号/双引号的时候,那么就必须加上双引号/单引号包进来,比如输入:
echo "It's a dog"
echo 'He says "This is good"'
输出:
It's a dog
He says "This is good"
2. 环境变量和用户变量
2.1 环境变量
可以通过set命令来查看当前环境变量,输入set|more 来分页显示结果。
set|more
输出
BASH=/bin/bash
BASHOPTS=checkwinsize:cmdhist:complete_fullquote:expand_aliases:extglob:extquote:force_fignore:histap
pend:interactive_comments:progcomp:promptvars:sourcepath
通过在环境变量名的前面加上美元符号$可以把该变量的内容取出来,建立test2.sh脚本并输入:
#!/bin/bash
# print environment parameter
echo -n "UID is "
echo $UID
echo -n "HOME is "
echo $HOME
输出:
UID is 1000
HOME is /home/aitian
注意:上面的美元符号是取出环境变量的对应的值,所以如果不加上美元符号,那么输出的就是变量名本身了。如果字符串本身就有一个美元符号的话,那么可以加上转义反斜线(\),比如输入
echo “this paper cost is \$2”
输出:
echo “this paper cost is $2”
2.2 用户变量
用户能够定义自己的变量来临时存储一些数据,对用户变量赋值的时候用等于号(=),例如
var=-40
注意:等号左右两侧不能出现空格,否则会报错,例如
var = -40
运行时会报错 ,var: 未找到命令。
用户变量的值会根据赋值数据自动决定变量类型,用户变量也可以通过美元符号取值。和C语言不一样的是,用户变量在整个shell的运行阶段都是有效的,在运行结束的时候会释放。建立test3.sh如下
#!/bin/bash
var_num=100
var_str="wulinwaizhuan"
echo "var_num is $var_num var_str is $var_str"
var_num=-100
var_str="baizhantang"
echo "var_num is $var_num var_str is $var_str"
输出:
var_num is 100 var_str is wulinwaizhuan
var_num is -100 var_str is baizhantang
注意:如果要将一个用户变量的值赋给另一个用户变量,也要用美元符号,例如建立test4.sh
#!/bin/bash
var1="wulinwaizhuan"
var2=$var1
var3=var1
echo "var2 is $var2,var3 is $var3"
输出:
var2 is wulinwaizhuan,var3 is var1
3. 命令替换
有时候需要将一条指令的运行结果赋值给一个变量,可以通过两个方法:
(1)在指令的两端加上反引号(`),比如a=`ls`,这个反引号在键盘左上角esc键盘的下一个
(2)通过美元符号加上小括号,比如a=$(ls)
新建test3.sh如下:
#!/bin/bash
a=`ls`
echo $a
a=$(ls $HOME)
echo $a
运行输出:
count_exe.sh isPhone.sh test11.sh test12.sh test19.sh test1.sh test2.sh test3.sh test4.sh test5.sh test.sh test.txt
at examples.desktop GoProject protobuf352 pycharm-community-2018.3.4 QtProject wget-log
4. 输入输出重定向
当前脚本的输入都是通过读取键盘的输入,输出是直接显示到屏幕上。而输入输出重定向能够把输入输出扩展到其他位置,比如从文件中读取或者输出到文件中。
4.1 输入重定向
输入重定向是把文件中的内容输入作为内容,输入给对应的指令。例如输入:
cat < test1.sh
输出:
#!/bin/bash
#This is first shell script to print hello world
echo "hello world"
这就是把test1.sh的内容输入给cat这个指令,cat指令会把对应的输入打印到屏幕上,再举一个例子,输入:
wc < test1.sh
输出:
3 13 80
这三个数字分别代表test1.sh这个文件的行数,单词个数和字节个数
4.2 输出重定向
输出重定向可以把结果写到文件中而非打印到屏幕上,例如输入:
date +%y%m%d > tmp.txt
当tmp不存在的时候会去自动创建这个文本写入,查看tmp.txt中的内容,cat tmp.txt
191201
注意:这里重定向会覆盖原来的内容,如果想要不覆盖,而是在后面追加的话使用符号 >>,例如输入:
ls >> tmp.txt
输出tmp.txt内容,cat tmp.txt:
191201
count_exe.sh
isPhone.sh
5 管道
通过重定向可以把输入输出重定向到文件中,如果是两个指令之间呢,两个指令之间如果要传输数据的话怎么办呢?当然用重定向间接地以类似于缓冲区的形式传递也是可以的,不过通过管道更加方便。
比如通过管道把ls输出的结果输入到sort排序这个命令中,输入:
ls | sort
输出:
count_exe.sh
isPhone.sh
这里的|就是管道,注意,管道左右两侧的指令并不是说左侧先执行,然后把结果输入到缓冲区然后右侧的指令再从缓冲区里面去读取。管道并不存在缓冲区,左侧指令一有结果右侧指令立即就有输入。
6 数学操作
数学上的加减乘除等shell脚本也能运行,shell提供两个方法执行数学运算:expr和方括号
6.1 expr命令
例如输入:
expr 2 -5
输出:
-3
但是expr有一个缺点导致她并不常用,expr不会自动去转义一些特殊符号,比如乘法符号*,输入:
expr 3 * 5
输出:
expr: 语法错误
加上反斜线可以解决这个问题,输入:
expr 3 \* 5
输出:
15
6.2 方括号
通过美元符号加中括号把数学表达书框起来的形式也能够完成数学运算,并且这种方式不需要转义,使用更加方便,建议以后使用这个方式,例如输入:
#!/bin/bash
var1=3
var2=$[3 + 3]
var3=$[$var1 + $var2]
var4=$[$var3 * 2]
var5=$[2 * ($var3 - $var4)]
echo "var1=$var1,var2=$var2,var3=$var3,var4=$var4,var5=$var5"
var6=$[100 / 30]
echo "var6=$var6"
输出:
var1=3,var2=6,var3=9,var4=18,var5=-18
var6=3
可以看出var1~var5都计算没问题,但是var6结果并不精确。这是因为shell只能支持整数运算。如果想要在shell中使用小数运算的话可以使用bc命令。
7. 查看指令退出的状态码和退出shell
7.1 查看指令退出的状态码
类似于C语言的函数返回值,其实每一个指令都会有一个返回的状态码,上一条指令结束之后会返回一个0~255范围内的整数,当前指令可以获取该返回码的值,一般成功退出都会返回0,查询方式是读取$?的值。
例如输入:
date
echo $?
输出:
0
输入:
abcdef
echo $?
输出
127
这里的127代表无效指令的返回值。
7.2 退出shell
当我们shell脚本运行结束后,shell脚本带的返回码就是最后一条指令的返回码。不过可以exit指令来指定返回码。例如在shell脚本中输入:
#!/bin/bash
date
exit 4
然后在终端执行该脚本并打印$?值:
输入:
./test8.sh
输出:
2019年 12月 01日 星期日 22:54:10 CST
输入:
echo $?
输出:
4
8 总结与展望
8.1总结
(1)如何创建并运行一个shell脚本,包括shell的第一行和注释;
(2) shell如何读取环境变量,定义用户变量,用美元符号$取值;
(3) 命令替换,用反引号或者$()实现命令替换;
(4) 输入输出重定向,用符号<实现输入重定向,符号>实现输出重定向
(5) 通过管道实现命令之间的重定向
(6) 数学运算,通过expr或者$[]的形式实现数学运算,不过expr不太好用
(7) 命令的状态码,用$?查看上一条命令的状态码,用exit 可以指定shell的返回状态码
8.2 展望
下次更新将学习使用shell中的条件判断语句怎么写,也就是if then,以及case语句。