shell脚本-基础
编程基础
程序是指令+ 数据
程序编程风格:
过程式:以指令为中心,数据服务于指令
对象式:以数据为中心,指令服务于数据
shell 程序提供了编程能力,解释执行。
计算运行二进制指令。
编译执行:
高级语言--> 编译器--> 目标代码
如java,C#
解释执行:
高级语言--> 解释器--> 机器代码
如shell, perl, python
编程逻辑处理方式:
顺序执行
循环执行
选择执行
shell 编程:
过程式、解释执行
编程语言的基本结构:
各种系统命令的组合
数据存储:变量、数组等
表达式: a + b等
语句:if的等
shell脚本说明
shell 脚本:
包含一些命令或声明,并符合一定格式的文本文件
shell 脚本的用途有:
自动化常用命令
执行系统管理和故障排除
创建简单的应用程序
处理文本或文件
格式要求:
首行shebang 机制
#!/bin/bash
#!/usr/bin/python
#!/usr/bin/perl
....
#! 就是告诉系统,这个脚本文件需要使用指定的命令解释器来执行。
紧随 #!的是一个路径名,此路径指向用来解释此脚本的程序,它可以是shell,可以是程序设计语言,也可以是实用程序。
这个解释器从头( #!的下一行)开始执行整个脚本的命令,同时忽略注释。
shell脚本的创建和运行:
创建脚本:
使用文本编辑器vim等来创建文本。
第一行必须是shell声明序列#!,一般为#!/bin/bash。
其余行为执行的命令。
添加注释使用#,注释以#开头。
运行脚本:
给予执行权限,在命令行上指定脚本的绝对或相对路径
chmod +x FILE.sh
/PATH/TO/FILE.sh
直接运行解释器,将脚本作为解释器程序的参数运行
source or . +脚本,一般不这么用,这样会对当前环境进行影响
bash + 脚本,就不会影响外部工作环境
脚本规范:
脚本代码开头约定
1 、第一行一般为调用使用的语言
2 、程序名,避免更改文件名为无法找到正确的文件
3 、版本号
4 、更改后的时间
5 、作者相关信息
6 、该程序的作用,及注意事项
7 、最后是各版本的更新简要说明
脚本开头的示例:
#!/bin/bash
#-------------------------------------------------
#Filename:
#Description:
#Revision:
#Date:
#Author:
#Email:
#Phonenumb:
#Copyright:
#------------------------------------------------
脚本结构:
解释器:#!/bin/shell,等
配置变量:自己定义的变量,A=123等
功能描述:以#开头来说明接下来执行语句的作用
执行命令:指令+参数,包括各种语句表达式等
脚本调试:
检测脚本中的语法错误
bash -n /PATH/TO/FILE.sh
调试执行
bash -x /PATH/TO/FILE.sh
脚本中默认不支持别名
尽可能用命令的绝对路径
变量介绍
变量的作用:
数据暂存
参与运算
表示数据范围
强类型变量:
变量不经过强制转换,它永远是这个数据类型,不允许隐式的类型转换。
一般定义变量时必须指定类型、参与运算必须符合类型要求。
调用未声明变量会产生错误。
如 java,c#的变量
弱类型变量:
语言的运行时会隐式做数据类型转换。
无须指定类型,默认均为字符型。
参与运算会自动进行隐式类型转换。
变量无须事先定义可直接调用
如bash,php的变量
变量的命名规则:
不能使程序中的保留字,如if、for等。
只能使用数字、字母及下划线,且不能以数字开头。
需见名知义。
统一命名规则,即驼峰命名法
bash中的变量种类
根据变量的生效范围作为标准
本地变量: 生效范围为当前shell进程。对当前shell之外的其它shell 进程,包括当前shell的子shell 进程均无效。
环境变量: 生效范围为当前shell进程及其子进程。
局部变量: 生效范围为当前shell进程中某代码片断( 通常指函数)。
位置变量: $1, $2, ...来表示,用于让脚本在脚本代码中通过调用命令行传递给它的参数,大于9的数,就应该加大括号:${10}
特殊变量: $?, $0, $*, $@, $#,$$
本地变量
变量赋值:
name=value
引用value:
直接字串: name=“root"
变量引用: name="$USER"
命令引用: name=` COMMAND `; name =$(COMMAND)
变量引用:
${name}
$name
" " : 弱引用,其中的变量引用会被替换为变量值
' ': 强引用,其中的变量引用不会被替换为变量值,而保持原字符串
${name[$i]} i是变量,name[$i]也是变量
' ':最傻的那个 ;" ":中间傻 ; ` `:聪明
显示已定义的所有变量:
set
删除变量:
unset name
环境变量
变量声明和赋值:
export name=VALUE
declare -x name=VALUE
变量引用:
$name, ${name},"$name"(尽量用带括和带双引号的)
显示所有环境变量:
env
printenv
bash内建的环境变量
PATH,SHELL,USER,UID,HOME,PWD,SHLVL,LANG,MAIL,HOSTNAME,HISTSIZE,—
只读变量
只能声明,但不能修改和删除。
声明只读变量:
readonly name
declare -r name
先赋值再声明或者是声明赋值一起做,不然,声明过后就不能再赋值了
查看只读变量:
readonly –p
位置变量
在脚本代码中调用通过命令行传递给脚本的参数
$1, $2, ... : 对应第1 、第2 等参数,是脚本后面跟着的参数,且9以后需要加大括号:${10}
shift [n] 可以更换位置
$0: 命令本身
$*: 传递给脚本的所有参数,全部参数合为一个字符串
$@: 传递给脚本的所有参数,每个参数为独立字符串
$#: 传递给脚本的参数的个数
$@与$* 只在被双引号包起来的时候才会有差异
set - - 清空所有位置变量
涉及到位置参数,脚本前面放置这个
[ $# -lt 1 ] && echo "Usage:`basename $0` arg1... " && exit 10
转换变量类型
可以使用declare或者typeset来转换变量类型
[root@localhost ~]# a=1;b=2;c=a+b;
[root@localhost ~]# echo $c
a+b
[root@localhost ~]# typeset -i a;typeset -i b;typeset -i c;
[root@localhost ~]# a=1;b=2;c=a+b;
[root@localhost ~]# echo $c
退出状态
进程使用退出状态来报告成功或失败
0 代表成功,1 -255 代表失败
$?变量保存最近的命令退出状态
示例:
ping -c1 -W1 hostdown &> /dev/null
echo $?
bash 自定义退出状态码
exit [n]:自定义退出状态码
注意:
脚本中一旦遇到exit命令,脚本会立即终止;终止退出状态取决于exit 命令后面的数字
如果未给脚本指定退出状态码,整个脚本的退出状态码取决于脚本中执行的最后一条命令的状态码
算术运算
help let
let arg [arg ...]
运算
+, -, *, /, % 取模(取余), ** (乘方)
注:乘法符号有些场景中需要转义 , 如*
增强型赋值:
+=, -=, *=, /=, %=
自增和自减:
let var+=1
let var++
let var-=1
let var--
实现算术运算
let var= 算术表达式
var=$[ 算术表达式]
var=$(( 算术表达式))
var=$(expr arg1 arg2 arg3 ...) ##expr判断后面的变量是否为整数,但不能为0。
declare –i var = 数值
echo ‘ 算术表达式’ | bc
bc
$RANDOM (0-32767) ##bash内建的随机数生成器
echo $[$RANDOM%50] ##0-49 之间随机数
逻辑运算
true和false
1, 0
输出0为假
设置空为假
设置0为真
与:
1 与 1 = 1
1 与 0 = 0
0 与 1 = 0
0 与 0 = 0
或:
1 或 1 = 1
1 或 0 = 1
0 或 1 = 1
0 或 0 = 0
非:!
! 1 = 0
! 0 = 1
短路运算
短路与
第一个为0 ,结果必定为0
第一个为1 ,第二个必须要参与运算
短路或
第一个为1 ,结果必定为1
第一个为0 ,第二个必须要参与运算
异或:^
异或的两个值, 相同为假,不同为真
数值交换:
条件性执行操作符:&&和||
根据退出状态而定,命令可以有条件地运行。
&& 代表条件性的and、then,与
|| 代表条件性的or、else,或
条件测试:
判断某需求是否满足,需要由测试机制来实现,专用的测试表达式需要由测试命令辅助完成测试过程
评估布尔声明,以便用在条件性执行中
若真,则返回0
若假,则返回1
测试命令和表达式
test EXPRESSION
[ EXPRESSION ]
[[ EXPRESSION ]] ##支持扩展的正则表达式算法
注意:
EXPRESSION 前后必须有空白字符
多测试在使用
![](http://images2017.cnblogs.com/blog/1250974/201802/1250974-20180207000632435-1219260200.png)
数值测试:
-gt (great than) 大于
-ge (great equal) 大于等于
-eq (equal) 等于
-ne (not equal) 不等于
-lt (lower than) 小于
-le (lower equal) 小于等于
字符串测试:
== 等于
> ascii 码大于ascii码
< 小于
!= 不等于
=~ 左侧字符串能够被右侧的PATTERN所匹配
-z "STRING“ 字符串为空,空为真,不空为假
-n "STRING“ 字符串不空,不空为真,空为假
注意:
此表达式一般用于[[ ]] 中;扩展的正则表达式。
用于字符串比较时,用到的操作数STRING都应该使用引号。
文件测试
存在为真,不存在为假
存在性和类别测试:
-a|-e FILE: 是否文件存在
-b FILE : 是否存在且为块设备文件
-c FILE : 是否存在且为字符设备文件
-d FILE : 是否存在且为目录文件
-f FILE : 是否存在且为普通文件
-h|-L FILE : 存在且为符号链接文件
-p FILE : 是否存在且为命名管道文件
-S FILE : 是否存在且为套接字文件
文件权限测试:
-r FILE : 是否存在且可读
-w FILE: 是否存在且可写
-x FILE: 是否存在且可执行
测试的是实际权限,例如root就有大多数权限
文件特殊权限测试:
-u FILE : 是否存在且拥有suid 权限
-g FILE : 是否存在且拥有sgid 权限
-k FILE : 是否存在且拥有sticky 权限
文件大小测试:
-s FILE: 是否存在且非空
文件是否打开:
-t fd: fd表示文件描述符是否已经打开且与某终端相关
-N FILE: 文件自从上一次被读取之后是否被修改过
-O FILE : 当前有效用户是否为文件属主
-G FILE : 当前有效用户是否为文件属组
双目测试:
FILE1 -ef FILE2: FILE1与FILE2 是否指向同一个设备上的相同inode
FILE1 -nt FILE2: FILE1是否新于FILE2 (mtime)
FILE1 -ot FILE2: FILE1是否旧于FILE2
组合测试
命令
COMMAND1 && COMMAND2 并且
COMMAND1 || COMMAND2 或者
! COMMAND 非
如:[[ -r FILE ]] && [[ -w FILE ]]
表达式
EXPRESSION1 -a EXPRESSION2 并且
EXPRESSION1 -o EXPRESSION2 或者
! EXPRESSION 非
必须使用测试命令进行
示例:
[ -z “$HOSTNAME” -o $HOSTNAME "=="localhost.localdomain" ] && hostname shen
[ -f /bin/cat -a -x /bin/cat ] && cat /etc/fstab
括号的用法
小括号()
(子进程),小括号是开子进程了,开子shell,小括号内值,只能在括号内用。
中括号[ ]
[表达式],用于测试
大括号{ }
{ cmd ; cmd ; …. ; }不会开子shell
参数导入:read
使用read 来把输入值分配给一个或多个shell 变量。
使用read 从标准输入中读取值,给每个单词分配一个变量,所有剩余单词都被分配给最后一个变量。
示例:
read -p “Enter a filename: “ FILE
read a b c <<< "xxx yyy zzz"
展开命令行的优先级
优先级从高到低
把命令行分成单个命令词
展开别名
展开大括号的声明({})
展开波浪符声明(~)
命令替换$() 和 (``)
再次把命令行分成命令词
展开文件通配(* 、? 、[abc] 等等)
准备I/0 重导向(< 、>)
运行命令
防参数属性扩展
反斜线(\ )会使随后的字符按原意解释
$ echo Your cost: \$5.00
Your cost: $5.00
加引号来防止扩展
单引号(’ )防止所有扩展
双引号(” )也防止所有扩展,但是以下情况例外:
$ (美元符号)#变量扩展
` (反引号)#命令替换
\ (反斜线) #禁止单个字符扩展
! (叹号)#历史命令替换
$- 变量
echo $-
himBH
h:hashall ,
打开这个选项后,Shell会将命令所在的路径hash下来,避免每次都要查询,通过set +h 将h 选项关闭。
i:interactive-comments,
包含这个选项说明当前的shell的是一个交互式的 shell ,所谓的交互式shell, 在脚本中i 选项是关闭的。
m:monitor,
打开监控模式,就可以通过Job control 来控制进程的停止、继续,后台或者前台执行等。
B:braceexpand ,
大括号扩展
H:history ,
H选项打开,可以展开历史列表中的命令,可以通过!感叹号来完成,例如“!!” 返回上最近的一个历史命令,“!n”第 返回第 n个历史命令