编程基础
程序:指令+数据 程序编程风格: 过程式:以指令为中心,数据服务于指令 对象式:以数据为中心,指令服务于数据 shell程序:提供了编程能力,解释执行 编程基本概念: 顺序执行;循环执行;选择执行 shell编程:过程式、解释执行 编程语言的基本结构 各种系统命令的组合 数据存储:变量、数组 表达式:a+b 语句:if
shell脚本基础
shell脚本:包含一些命令或声明,并符合一定格式的文本文件 格式要求:首行shebang机制 #! /bin/bash #! /usr/bin/python #! /usr/bin/perl shell脚本的用途有: 自动化常用命令 执行系统管理和故障排序 创建简单的应用程序 处理文本或文件
创建shell脚本
第一步:使用文本编辑器来创建文本文件 第一行必须使用包括shell声明序列:#! #!/bin/bash 添加注释 注释以#开头 第二步:运行脚本 给予执行权限,在命令行上指定脚本作为解释器程序的参数运行 直接运行解释器,将脚本作为解释器程序的参数运行 脚本规范: 脚本代码开头约定 1.第一行一般为调用使用的语言 2.程序名,避免更改文件名为无法找到正确的文件 3.版本号 4.更改后的时间 5.作者相关信息 6.该程序的作用,及注意事项 7.最后是各版本的更新及简要说明 脚本的基本结构: #!SHEBANG CONFIGURATION_VARIABLES FUNCTION_DEFINITIONS MAIN_CODE shell脚本示例:
脚本调试
检测脚本中语法错误 bash -n /path/to/some_script 调试执行 bash -x /path/to/some_script
变量
变量:命名的内存空间 数据存储方式: 字符: 数值:整型、浮点型 变量:变量类型 作用:1.数据存储格式 2.参与的运算 3.表示的数据范围 强类型:变量不经过强制转换,它永远是这个数据类型,不允许隐式的类型转换。一般定义变量时必须指定类型、参与运算必须符合类型要求;调用未声明变量会产生错误。如java,c# 弱类型:语言的运行时会隐式做数据类型转换。无须指定类型,默认均为字符型;参与运算会自动进行隐式类型转换;变量无须事先定义可直接调用。如bash不支持浮点数,php 变量命名规则: 1.不能使用程序中的保留字:例如if,for 2.只能使用数字、字母及下划线,且不能以数字开头 3.见名知义 4.统一命名规则:驼峰命名法
bash中变量的变种
根据变量的生效范围等标准划分下面变量类型: 局部变量:生效范围为当前shell进程;对当前shell之外的其他shell进程,包括当前shell的子shell进程均无效 环境(全局)变量:生效范围为当前shell进程及其子进程(利用export声明即为环境变量) 本地变量:生效范围为当前shell进程中某代码片段,通常指函数 位置变量:$1,$2,...来表示,用于让脚本在脚本代码中调用命令行传递给它的参数 特殊变量:$?,$0(代表脚本名称),$*(代表所有参数),$@(代表所有参数),$#(代表参数数量),$$ 注意:#@与#*的区别在于#*会将所有位置参数当成一个整体 echo $$:查看当前shell运行的系统编号 pstree -p:查看当前系统运行的shell树状结构 scp命令:可以跨网络将本机数据发送到另外一台机器上 局部变量 变量赋值:name='value' 可以使用引用value: (1)可以是直接字串;name="root" (2)变量引用:name="$USER" (3)命令引用:name='COMMAND' name=$(COMMAND) 变量引用:${name} $name "":弱引用,其中的变量引用会被替换为变量值 '':强引用,其中的变量引用不会被替换为变量值,而保持源字符串 显示已定义的所有变量:set 删除变量:unset name 环境变量 变量声明、赋值 export name=VALUE declare -x name=VALUE 变量引用:$name,${name} 显示所有环境变量: env printenv export declare -x 删除变量 unset name bash内建的环境变量:PATH,SHELL,USER,UID,HOME,PWD,SHLVL,MAIL,HISTSIZE,- 等等。
只读和位置变量
只读变量:只能声明,但不能修改和删除 声明只读变量:readonly name declare -r name 查看只读变量:readonly -p 位置变量:在脚本代码中调用通过命令行传递给脚本的参数 $1,$2,...:对应第一,第二等参数,shift[n]换位置 $0:命令本身 $*:传递给脚本的所有参数。全部参数合为一个字符串 $@:传递给脚本的所有参数,每个参数为独立字符串 $#:传递给脚本的参数个数 $@ $* 只在被双引号包起来的时候才会有差异 set -- 清空所有位置变量
退出状态
进程使用退出状态来报告成功或失败 0代表成功,1-255代表失败 $?变量保存最近的命令退出状态 例如: print -c1 -W1 hostdown &> /dev/null echo $? 退出状态码 bash自定义退出状态码 exit[n]:自定义退出状态码 注意:脚本中一旦遇到exit命令,脚本会立即终止;终止退出状态取决于exit命令后面的数字;
如果未给脚本指定退出状态码,整个脚本的退出状态码取决于脚本中执行的最后一条命令的状态码
算术运算
bash中的算术运算:help let +,-,*,/,%取模(取余),**(乘方) 实现算术运算: (1)let var=算术表达式 (2)var=$[算术表达式] (3)var=$((算术表达式)) (4)var=$(expr arg1 arg2 ...) (5)declare -i var =数值 (6)echo '算术表达式' | bc 乘法符号在有些场景中需要转义,如* bash有内建的随机数生成器:$RANDOM(0-32767) echo $[$RANDOM%50]:0-49之间随机数 赋值:+=,-=,==,/=,%= let var OPER value:let count+=3 自增自减:let var +=1 ;let var++ ;let var -=1; let var--;
逻辑运算
条件测试
判断某需求是否满足,需要由测试机制来实现 专用的测试表达式需要由测试命令辅助完成测试过程 评估布尔声明,以便用在条件性执行中 若真,则返回0 若假,则返回1 测试命令: test EXPRESSION [EXPRESSION] [[EXPRESSION]](这种情况适用于带有正则表达式的情况)
注意:EXPRESSION前后必须有空白字符 条件性的执行操作符 根据退出状态而定,命令可以有条件地运行 && 代表条件性的AND THEN || 代表条件性的OR ELSE 例如: grep -q no_such_user /etc/passwd || echo 'No such user' 输出:No such user ping -c1 -W2 station &> /dev/null > && echo "Station1 is up" > ||(echo 'Station1 is unreachable';exit1) 输出:Station1 is up test命令(内部命令,查看帮助:help test) 长格式的例子: test "$A" == "$B" && echo "Strings are equal" test "$A" -eq "$B" && echo "Integers are equal" 简写格式的例子: ["$A" == "$B"] && echo "Strings are equal" ["$A" -eq "$B"] && echo "Integers are equal" bash的数值测试 -v VAR:变量VAR是否设置 数值测试: -gt 是否大于 -ge 是否大于等于 -eq 是否等于 -ne 是否不等于 -lt 是否小于 -le 是否小于等于 bash的字符串测试 == 是否等于 > ascii码是否大于ascii码 < 是否小于 != 是否不等于 =~ 左侧字符串是否能够被右侧的PATTERN所匹配(此表达式一般用于[[]]中;扩展的正则表达式) -z "STRING" 字符串是否为空,空为真,不空为假 -n "STRING" 字符串是否不空,不空为真,空为假 注意:用于字符串比较时用到的操作数都应该使用引号
bash的文件测试
存在性测试 -a FILE:同-e -e FILE:文件存在性测试,存在为真,否则为假 存在性及类别测试 -b FILE:是否存在且为设备文件
示例:[-f /etc/issue] && echo true
[-d /etc/] && echo true
bash文件权限测试
文件权限测试: -r FILE:是否存在且可读 -w FILE:是否存在且可写 -x FILE:是否存在且可执行 文件特殊权限测试: -u FILE:是否存在且拥有suid权限 -g FILE:是否存在且拥有sgid权限 -k FILE:是否存在且拥有sticky权限
bash的文件属性测试
文件大小测试 -s FILE:是否存在且非空 文件是否打开: -t fd:fd文件描述是否在某终端已经打开 -N FILE:文件自从上一次被读取之后是否被修改过 -O FILE:当前有效用户是否为文件属主 -G FILE:当前有效用户是否为文件属组 双目测试: FILE1 -ef FILE2:FILE1是否是FILE2的硬链接 FILE1 -nt FILE2:FILE1是否新于FILE2(mtime) FILE1 -ot FILE2:FILE1是否旧于FILE2
bash的组合测试条件
第一种方式: COMMAND1 && COMMAND2 COMMADN1 || COMMADN2 !COMMAND 如:[[ -r FILE ]] && [[ -w FILE ]] 第二种方式: EXPRESSION1 -a EXPRESSION2 EXPRESSION1 -o EXPRESSION2 !EXPRESSION 必须使用测试命令进行 示例:[ -z "$HOSTNAME" -o "$HOSTNAME"=="localhost.localdomain"] && hostname www.ccsu.com [ -f /bin/cat -a -x /bin/cat] && cat /etc/fstab
使用read命令来接收输入
使用read来把输入值分配给一个或多个shell变量 -p 指定要显示的提示 -s 静默输入,一般用于密码 -n N 指定输入的字符串长度 -d '字符'输入结束符 -t N TIMEOUT为N秒 read 从标准输入中读取值,给每个单词分配一个变量,所有剩余单词都被分配给最后一个变量 read -p "Enter a filename:" FILE
流程控制
过程式编程语言: 顺序执行 选择执行 循环执行
条件选择if语句
if语句示例: read -p"please onput your age:" age [[ "$age" =~ [0-9]+$ ]] ||{echo your age is false;exit10;} if [ "$age" -gt 0 -a "$age" -le 18];then echo "you are young" elif[ "$age" -gt 18-a "$age" -le 50];then echo woek hard elif ["$age" -gt 50 -a "$age" -le 80];then echo "very ok" else echo "you do not come from earth" fi
条件判断:case语句
case语句示例: read -p"Do you agree?tes or no:"anwser case $answer in [Yy]|([Yy][Ee][Ss]) echo your answer is yes ;; [Nn]|[Nn][Oo]) echo your answer is no ;; *) echo your answer is false ;; esac
循环
循环执行 将某段代码重复运行多次 重复运行多少次 循环次数事先已知 循环次数事先未知 有进入条件和退出条件 for;while;until
for循环
for循环示例1 显示root下所有的txt格式文件: for name in `ls /root/*.txt`;do echo "$name";done for循环示例2 求1-100之间的奇数和 sum=0;for number in `seq 1 2 100`;do let sum+=number;done;echo "sum is $sum"
while循环
while循环示例1 求1-100之间的奇数和 sum=0;i=1;while ["$i" -le 100];do let sum+=i;let i+=2;echo "sum is $sum"
until循环
循环控制语句continue
循环控制语句break
for循环的特殊用法:
for循环的特殊用法示例: 求1-100之间的奇数和 for((sum=0,i=1;i<100;i+=2));do let sum+=i;done;echo "sum is $sum"
函数介绍
函数function是由若干条shell命令组成的语句块,实现代码重用和模块化编程 它与shell程序形式上是相似的,不同的是它不是一个单独的进程,不能独立运行,而是shell程序的一部分 函数和shell程序比较相似,区别在于: shell程序在子shell中运行 而shell函数在当前shell中运行。因此在当前shell中,函数可以对shell中变量进行修改
定义函数
cat /etc/init.d/functions 查看系统自定义的函数
函数使用
函数返回值
函数返回值示例: checkip(){ [[ "$1" =~ ^([0-9]{1,3}.){3}[0-9]{1,3}$ ]] && echo "This is a IP" || {echo "This is not IP" ;return 10;} } 注意:返回值返回给了调用者
交互式环境下定义和使用函数
在脚本中定义及使用函数
定义一个ip检查函数 checkip(){ [[ "$1" =~ ^([0-9]{1,3}.){3}[0-9]{1,3}$ ]] && echo "This is a IP" || echo "This is not IP" } 调用函数 checkip 删除函数 unset checkip
使用函数文件
创建函数文件
载入函数
检查载入函数
执行shell函数
删除shell函数
函数参数:
函数变量
局部变量示例
函数递归示例
函数递归示例
fork炸弹
数组
数组赋值
引用数组
数组数据处理
数组示例1
数组示例2