一 shell基础
1. Shell 程序本身的功能是很弱的,比如文件操作、输入输出、进程管理等都得依赖内核。我们运行一个命令,大部分情况下 Shell 都会去调用内核暴露出来的接口,这就是在使用内核,只是这个过程被 Shell 隐藏了起来,它自己在背后默默进行,我们看不到而已。
2. Shell 本身支持的命令并不多,功能也有限,但是 Shell 可以调用其他的程序。这使得 Shell 命令的数量可以无限扩展,其结果就是 Shell 的功能非常强大,完全能够胜任 Linux 的日常管理工作,如文本或字符串检索、文件的查找或创建、大规模软件的自动部署、更改系统设置、监控服务器性能、发送报警邮件、抓取网页内容、压缩文件等。
3. Shell 也是一种编程语言,它的编译器(解释器)是 Shell 这个程序,Shell 主要用来开发一些实用的、自动化的小工具,而不是用来开发具有复杂业务逻辑的中大型软件,例如检测计算机的硬件参数、搭建 Web 运行环境、日志分析等,
二 . Hello world
1.扩展名为.sh代表shell,新建test.sh
2.在test.sh中输入
3. 解释说明
第一行:!# 是一个约定的标记,告诉系统这个脚本需要哪个解释器来执行,后面的/bin/bash指明解释器的具体位置;
第二行:echo命令用于向标准输出文件输出文本;
4.在test.sh中输入
5.解释说明:
第五行:read 表示从终端读取用户输入的数据,并赋值给 PERSON;read用来从标准输入文件,读取用户输入的数据
第六行:表示输入输入变量PERSON的内容,在变量前面要加一个$,否则会当成一个字符串处理;
6.将shell脚本作为程序运行
7.解释说明:
第二行: chmod +x 给脚本添加执行权限;
第三行:./表示当前目录,在当前目录下执行test.sh脚本
注意:这种方式,脚本头 #!/bin/bash一定要写对
echo $$ 获取当前进程的PID
shell编程
一 变量
1.变量
(1).定义变量
解释说明: 如果value 不包含任何空白符(tab 缩进),不需要加引号;如果包含必须加引号,
变量的名字必须以字母或者下划线开头,不能以数字开头
注意 : = 前后都不可以出现空格
(2).变量的使用:
解释说明:使用一个定义过的变量,只需要在变量前加上$ 即可;也可以加一个花括号,加不加都可以;花括号是为了帮助解释器识别变量的边界;
注意 : 推荐给所有的变量加花括号
(3).修改变量的值
(4).单引号和双引号的差别
解释说明:' ' 单引号包围的,里面是什么就输出什么,即使里面有变量和内容,都原样输出;
" " 双引号包围的,输出时会先解析里面的的变量和内容;
注意 : 如果变量是数字,不需要加引号;如果需要原样输出的加单引号;其他没有特殊要求的 都需要加双引号。
(5) .将命令的结果赋值给变量
(6).只读变量
(7).删除变量
2.变量的作用域
(1)局部变量
解释说明:在shell函数中定义的变量默认也是全局变量,他和在函数外定义的变量效果一样
想要编程局部变量 ,可以在定义时加上local命令
(2)全局变量
变量在整个shell进程中都有效,在shell中定义的变量,默认都是全局变量。整个shell进程,而不是当前的shell脚本,每打开一个shell窗口就是一个shell进程。
以下两个shell脚本a.sh 和b.sh
打开一个shell窗口
解释说明:这三条命令是在同一个进程中执行的,在shell窗口中以命令行形式定义的变量,在a.sh中生效了,在a.sh中定义的b,在b.sh中也生效了。
(3)环境变量
使用export 命令将全局变量导出,全局变量就会在所有的子进程中生效,这称为 环境变量;
注意 : 两个没有父子关系的进程是不可以传递环境变量的;
通过export命令导出的全局变量只对当前shell进程以及子进程有效,如果父进程被关闭了,其他进程也无法使用了,环境变量是临时的。
3.命令替换
(1)反单引号 `` 和 $() 都可以完成命令替换
注意 : 多数情况下 `` 和 $() 是等价的,但是$() 可以用于嵌套$() ,反单引号`` 容易和单引号混淆,建议使用$()
4.位置参数
(1)给函数传递位置参数
(2)给脚本文件传递位置参数
注意: 如果参数个数太多,需要用${n} 来接收
5.特殊变量
(1)给函数传递参数
(2)$@ $* 区别
解释说明:当他们不被双引号包裹的时候没有任何差别;
当他们被双引号包裹的时候:"$*" 会把所有参数看成一份整体数据;"$@" 会把每个参数 看成一份数据,彼此之间是独立的
二 字符串
1.字符串
可以由 单引号包裹 '' ,双引号包裹 "" ,不被引号包裹; 他们之间的区别 见上方变量中的第4条 单引号和双引号的差别
具体使用看下面例子,不做细致说明了
2.获取字符串长度
${#str_name} 获取字符串长度
3.字符串拼接
将多个字符串排放在一起就能实现拼接,不需要使用任何运算符
以下是拼接的多种形式
4.字符串截取
(1)从左边开始截取
格式: #${string:star:length}
解释说明: 从左边开始计数 start其实位置 length长度;
length 可以省略 从开始位置截取到最后;
从0开始计数;从左往右截取
(2)从右边开始截取
格式: #{string:0-start:length}
解释说明: 0- 固定写法,表示从右边开始计数;
length 可以省略 从开始位置截取到最后;
起始数字是1;从左往右截取
(3)从指定字符开始截取
使用#截取右边字符
格式: ${string#*charts}
解释说明:charts 表示指定字符串;*通配符 任意长度的字符串;*charts 意思是忽略左边所有字符串,直到遇到第一个charts就开始截取
格式:${string##*charts} 用法同上 不同的是直到遇到最后一个指定字符串才结开始截取
使用%截取左边字符
格式:${string%charts*} 截取charts 左边的字符,忽略右边的字符;
%和%%的区别于#和##用法一直
汇总
三 数组
(1).数组的定义
array_name=(value1 value2 value3 value4)
解释说明:用()表示数组;数组元素之间用空格隔开;=两边不能有空格
解释说明:shell数组是弱类型,不要求所有元素类型都相同;
数组长度不是固定的,定义之后还可以添加元素;
可以给特定元素赋值;
根据下标可以获取指定位置字符;
(2)获取数组长度
解释说明:@和* 用法一样,任选其一就可以了
(3)数组合并
解释说明:将数组扩展成列表再合并再一起
(4)删除数组元素
解释说明:unset关键字来删除数组元素
四 shell内建命令
可以使用 type 来确定命令是否属于内建命令
内建命令比外部命令执行快,执行外部命令时不但会触发磁盘io,还是单独fork一个进程来执行,执行完后,还要推出这个进程,执行内建命令相当于调用当前shell的一个函数
(1)alias 和unalias
(2)echo 和 echo -n , echo -e
(3)read
read常用选项
(4)exit
退出当前hell进程,退出状态在0~255之间,只有状态为0的时候表示退出成功,其他都表示失败;
(5)declare
五 数学计算
(1)(( 表达式 ))
解释说明:
a. 只能对整数进行运算;
b. 表达式可以有一个或多个,多个表达式之间用,分隔,多个表达式时,以最后一个表达式为命令最终的执行结果;
c. 在(( ))中的变量不需要加$,(( ))会自动解析变量名;
d. 需要立即输出表达式的结果时,需要在(( ))前面加$
e. (( ))可以做一些稍微复杂的计算:如下图所示:
(2)let
格式: let 表达式 ; let '表达式' ; let "表达式"
解释说明:
a.用法同(( ));
b.表达式中有特殊字符时,需要用" " 或者 ' '包围起来;
c.不同于(( )) 的是:(( )) 多个表达式之间用 , 隔开;let 多个表达式之间用空格隔开
(3)bc
六 .if else
1.语法
解释说明:
a.如果 condition 条件成立,那么执行 then 后面的语句;如果不成立,不会执行任何语句,最后以fi来闭合;
b.如果condition 和 then 写在同一行,则condition后需要用;隔开
2. if elif else
3. test 等价于 [ 表达式 ]
还有test与文件检测相关的,暂不做笔记说明 ,具体使用请点击:test检测文件(http://c.biancheng.net/view/2742.html)