shell脚本-基础

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个历史命令
posted @ 2018-02-07 00:07  shenxm  阅读(328)  评论(0编辑  收藏  举报