Linux shell
# 为什么要学习Shell呢?
不管是做运维还是做android系统开发,都要学习shell
这里我们主要是针对android系统开发,AOSP-android开源项目。
我们学习Shell有两个目的,一个是能看懂编译控制脚本,另外一个是能够修改或者说可以编写编译控制脚本。
什么是Shell
如果你接触计算机多年,可能有人跟你说过黑乎乎的命令行窗口就是shell,Windows有命令行窗口,而Linux各个发行版本也有命令行窗口。
我们先不管这个。我们平时都是通过UI交互来控制操作系统。
从一个整体的角度看操作系统,应该如下:
而shell命令行窗口就是前面我们提到的小黑窗了。对于一般的用户来说,比较常用的是可视化操作,比如说复制一个文件,而shell命令行窗口里输入命令也可以实现复制文件。
shell能做的,可视化操作不一定有,而可视操作有的,shell一定有。
shell就是黑乎乎的命令行窗口,对不对呢?应该说还不够准确,这只是其中一个入口。除了使用命令行窗口输入命令,编程语言使用系统的API也可是可以调用shell命令的,我们也可以通过编写shell脚本去执行。
shell应该是一个命令解析器,解析来自脚本的命令或者第三方应用的指令给操作系统。
Shell脚本
接下来我们就开始学习一下shell脚本,环境限制哈,今天周六休息写这篇文章,在家里没有服务器,所以不能结合实际的AOSP实际例子分析了,但是理解了这些知识,也是可以看懂shell脚本的。
shell解析器
我现在有一个树莓派的机器,里面也是基于Linux的一个系统,怎么查看解析器呢?
而默认的解析器则是/bin/sh
一般来说,我们在写shell脚本的时候,需要指定解析器,否则就使用默认的解析器。
shell开始
shell脚本以
#!/bin/bash
开头,看过AOSP里shell脚本的同学可能有印象,它并没有以这个开头,如果不指定的话,默认就是/bin/bash作为shell的解析器。
hello world!
wq保存,解析一下:
除了用sh以外,我们还可以这样子执行脚本:
但是调用./helloworld.sh的时候要注意,先修改权限,否则没法执行这个脚本的。
eg2:
我们再来一个例子,把上面的动作转在命令去完成:
1、在~/shell_code/目录下面创建一个名字为helloworld2.sh的文件
2、往这个文件里写入内容:输出helloworld
这其实对着我们AOSP里的自动控制流程了,一些重复的操作就可以抽象出来,用脚本代替。
执行一看看结果如何?
shell变量
在shell脚本中,变量分成两类,一类是系统定义的变量,一类是用户自己定义的变量。
常用的系统变量有哪些呢?
比如说前面提到的:$SHELL,还有$HOM, $USER ,$PATH ,$PWD….
我们可以输出来看看它们的值是什么:
执行结果:
这个了解一下就好,以后写脚本的时候可以使用到,写多几次就记住了。
知道这些,如果以后要复制文件呀,或者添加环境变量之类的就简单得多了,对吧。
自己定义变量怎么玩呢?
跟我们的java不一样,直接变量=值就可以了。
不需要生命类型
eg:
a=10
echo $a
注意哦,赋值没有空格。
字符串也一样,shell脚本是若类型语言,不类型,跟javaScript一样。
静态变量,也就是常量,只读的哦,不可以unset
readonly b=20
echo $b
#看结果会不会报错
unset $b
定义变量有什么规则呢?
- 名字,明明规则不多说了,都是有经验的开发人员;
- 赋值等号两边没有空格;
- 赋值的内容默认为字符串类型,需要进行一个转换才能进行运算;
- 参数/字符串有空格,需要用双引号以表示成一体的。
如何把局部变量提升成全局变量,让其他地方可以访问呢?
比如说我们在shell脚本里定义一个变量VAR=10,怎么样可以直接在命令行中访问呢?
var.sh
#!/bin/bash
echo $VAR
shell中特殊的变量
$n,其中n表示数字,从0开始,一般不超过10
$n表示什么呢?我们输出一下吧:
执行结果:
我们java的main函数也是可以传参数的,这里面的话大家理解一下就好,当我们执行一下shell的时候,可以传进来参数。
如果是$1那么是第二个参数,我再修改一个代码:
相信大家理解了吧:
$#,这也是一个特殊变量,它表示的是参数的个数。在java中可以用不定参数来表示,然后以数据的形式进行获取。
在shell中,我们获取到了参数的个数以后,可以进行遍历,下面我们就举例说明一下吧:
这里面我们还没有学到循环语句,我们就只读取参数的个数即可
#!/bin/bash
echo "parameter count is --- > $#"
shell中的运算符 对于运算符大家应该很熟悉了吧
上图来自己菜鸟
看这篇文章的都是有经验的程序员了,这些东西应该非常简单的
要注意的点:expr后面要有空格,运算符两边要有空格,会看就好
这里跟赋值不一样,需要双等号的两边需要有空格
基本格式是这样子的$((运算表达式)) 或者写成$[运算表达式]
条件语句
语法:
[空格 条件 空格]
条件两边要有空格
条件里只要有内容就为true,除非为空为false,接着就是判条件
比如说:[ abc ] 返回true,[]返回false
常用的条件判断
= 比较字符串
-lt 小于(less than)
-gt 大于 (greater than)
-ne 不等于 (not equal)
-eq 等于 (equal)
-le 小于等于 (less equal)
-ge 大于等于 (greater equal)
记住几个单词怎么切换都行对吧!
接直来除了这些以外,我们还有可能判断到文件是否可以读写之类的
-r 判断文件是否可读,true表示可读,false表示不可读
-w 判断写
-x 判断是否可执行
-e 判断文件是否存在
-f 判断是不是文件
-d 判断是不是一个目录
后面我们结合条件语句来写一些例子
shell中的流程语句
流程控制语句在各种编程言中都有的呢,在shell中也有
if的判断
case语句
for循环
while循环
if判断语句 先上代码吧,我们判断两个数是否相等,用到前面的
执行结果怎么样的呢?当然是输出a=b啦
if语句有两种写法:
if [ 条件 ];then
程序逻辑
fi
第二种写法,就是then换下来:
if [ 条件语句 ]
then
程序语句
fi
要注意的地方是if后面有空格,条件语句两边有空格
多写几次吧,写错了以后就记住了。
再来一个elif,在java里是else if,在shell里是elif
比如说我们判断输入的内容:
执行结果如下:
case语句
case语句的话,这里我们不直接给出格式了,直接上代码
因为代码更容易看懂
#!/bin/bash
case $1 in
1)
echo "female"
;;
2)
echo "male"
;;
*) echo "unknow"
;;
esac
一看代码就知道了吧,按模板去套就可以了。
## for循环语句
这个格式是怎么样子的呢?
for((初始值;条件;变量控制语句))
do
循环体
done
比如我们输出一个三解形
除了这种,还有
for loop in 1 2 3 4
do
echo $loop
done
while循环
while循环的语法
while [ 条件 ]
do
语句
done
#!/bin/bash
total=0
i=1
while [ $i -le 100 ]
do
total=$[$total+$i]
i=$[$i+1]
done
echo "total is $total"
执行结果
读取控制台的输入read
我们AOSP里,要选择编译的版本,这个时候,需要从控制台窗口中读取号码,然后才去进行编译。
怎么样读取控制台的输入呢?
read
选项有:
-t:等待时间,单位为秒
-p:指定读取值时的提示符:
eg:
#!/bin/bash
echo "please input the version you want to compile:\n"
echo "1.user-version\n2.engineer-version"
read -p "your selected version is:" version
if [ $version -ne 1 -a $version -ne 2 ]
then
echo "version not right"
else
case $version in
1)
echo "you selected version is user-version"
;;
2)
echo "you selected version is engineer-version"
;;
esac
fi
echo "your input is $version"
函数
函数的话我们主要分为两块,一部分是系统函数,另外一部分则是我们自己写的函数。
常用的系统函数
basename 全路径名称,获取到文件的名字
dirname 全路径名称,获取除文件名以外的路径地址
这两个在自动化编译的时候,关于路径的处理用得上
自定义函数
怎么样写自己的函数呢?之前在分析编译脚本的时候,就有lunch这个函数了,用于加载要编译的版本。
定义函数:
[function] 函数名[()]
{
函数体
}
调用:
函数名
举例子
#!/bin/bash
function sum()
{
total=0
total=$[$1+$2]
echo "total is --> $total"
}
read -p "please input first number:" number1
read -p "please input second number:" number2
sum $number1 $number2
执行结果:
学会以上这些内容,结合例子,多写代码,看懂是没问题的,要写出来,还得需要一些时间。