Linux基础教程之shell脚本使用入门
1、编程基础
- 程序:指令+数据
- 程序编程风格:
过程式:以指令为中心,数据服务于指令
对象式:以数据为中心,指令服务于数据
- shell程序:提供了编程能力,解释执行
2、程序的执行方式
- 计算机:运行二进制指令
- 编程语言:
低级:汇编
高级:
编译:高级语言– >编译器–> 目标代码
C,C++,C#,Go
解释:高级语言–> 解释器–> 机器代码
shell,perl , Python , JAVA
JavaScript , ruby ,PHP
3、编程基本概念
- 编程逻辑处理方式:
顺序执行
循环执行
- shell编程 :过程式、解释执行
编程语言的基本结构:
各种系统命令的组合
数据存储:变量、数组
表达式:a+b
语句:if
4、shell脚本基础
- shell脚本:
包含一些命令或声明,并符合一定格式的文本文件
- 格式要求:首行shebang机制
#!/bin/bash
# ! /usr/bin/Python
#!/usr/bin/perl
- shell脚本的用途有:
> 自动化常用命令
> 执行系统管理和故障排除
> 创建简单的应用程序
> 处理文本或文件
5、创建shell脚本
- 第一步:使用文本编辑器来创建文本文件
> 第一行必须包括shell声明序列:#!
#!/bin/bash
> 添加注释
注释以#开头
- 第二步:运行脚本
> 给予执行权限,在命令行上指定脚本的绝对或相对路径
> 直接运行解释器,将脚本作为解释器程序的参数运行
6、shell脚本示例
#!/bin/bash
#Author :Li
#Version : 1.0
#Date : 2017-04-01
#Description :The script displays system information
echo”Greetings.The date and time are $(date)”
echo “Your working directory is : $(pwd)”
7、脚本调试
- 检测脚本中的语法错误
bash -n /path/to/some_script
- 调试执行
bash -x /path/to/some_script
8、变量
- 变量:暂时存放数据的地方,一个具有名称的内存地址空间。
数据存储方式:
字符:
数值:整形,浮点型
- 变量:变量类型
作用:
1、数据存储格式
2、参与的运算
3、表示的数据范围
类型:
字符
数值:整形、浮点型
- 强类型:变量不经过强制转换,它永远是这个数据类型,不允许隐式的类型转换。一般定义变量时必须指定类型参与运算必须符合类型要求;调用未声明变量会产生错误
如 java,c#
- 弱类型:语言的运行时会隐式做数据类型转换。无须指定类型,默认均为字符型;
参与运算会自动进行隐式类型转换;变量无须事先定义可直接调用
如:bash不支持浮点数,php
- 变量命名法则:
1、不能使程序中的保留字:例如if,for
2、只能使用数字、字母及下划线,且不能以数字开头
3、见名知义
4、统一命名规则:驼峰命名法
- 变量的命名规范
>使用英文字母,数字及下划线组成;
>开头第一个字母不能使用数字
>Beijing
>BEIJING
>BeiJing
>Bei_Jing
>_Bei_Jing
9、bash中变量的种类
- 根据变量的生效范围等标准:
本地变量(全局变量):生效范围为当前shell进程;对当前shell之外的其它shell进程,包括当
前shell之外的其它shell进程,包括当前shell的子shell进程均无效
环境变量:生效范围为当前shell进程及其子进程
局部变量(私有变量):生效范围为当前shell进程中某代码片段(通常指函数)
位置变量:$1,$2,…来表示,用于让脚本在脚本代码中调用通过命令行传递给它的参数
特殊变量:$?,$0,$*,$@,$#,$$
10、本地变量
- 变量赋值:name=’value’
- 可以使用引用value:
(1)可以是直接字串;name=“root”
(2)变量引用:name=”$USER”
(3)命令引用:name=`COMMAND` name=$(COMMAND)
- 变量引用:${name} $name
“”:弱引用,其中的变量引用会被替换为变量值
” :强引用,其中的变量引用不会被替换为变量值,而保持原字符串
- 显示已定义的所有变量:set
- 删除变量:unset name
11、环境变量
- 变量声明、赋值:
export name=VALUE
declare -x name=VALUE
- 显示所有环境变量:
env,printenv,export,declare -x,set
- 删除:unset name
- bash有许多内建的环境变量:PATH ,SHELL ,USRE,UID,
HISTSIZE,HOME,PWD,OLDPWD,HISTFILE
12、环境变量
- $PATH 命令的搜寻路径
- $OLDPWD 前一个工作目录
- $LANG 目前的工作语系
- $BASH bash的完整路径名
- $BASH_VERSION Bash的版本
- $HISTCONTROL 控制指令是否存入历史文件中
- $OSTYPE 显示系统类型
- $MAIL 存放邮件的文件
- $MAILCHECK 多久检查一下邮件
- $PWD 当前路径
- $SSH_TTY 当前登录的TTY
- $SHLVL 当前shell在第几层
- $RANDOM 随机数
13、只读和位置变量
- 只读变量:只能声明,但不能修改和删除
>声明只读变量:
readonly name
declare -r name
>查看只读变量:
readonly -p
- 位置变量:在脚本代码中调用通过命令行传递给脚本的参数
$1,$2, ….: 对应第1、第2等参数,shift [n]换位置
$0:命令本身
$*:传递给脚本的所用参数,全部参数合为一个字符串
$@:传递给脚本的所有参数,每个参数为独立字符串
$#:传递给脚本的参数的个数
$@ $* 只在被双引号包起来的时候才会有差异
set — 清空所有位置变量
14、算术运算
- bash中的算术运算:help let
+,-,*,/,%取模(取余),**(乘方)
实现算术运算:
(1)let num=算术表达式 let r=9+9
(2)var=$[算术表达式] r=$[9+9]
(3)var=$((算术表达式)) r=$((9+9))
(4)外部命令 expr expr 8+3
(5)declare -i var = 数值 declare -i r=9+9
(6)echo ‘算术表达式’ | bc echo “8+8” | bc
- 乘法符号有些场景中需要转义,如*
- bash有内建的随机数生成器:$RANDOM(0-32767)
echo $[$RANDOM%50]:0-49之间随机数
- 思考:
- unset i
- echo $((12+$i))是否可以执行
15、赋值
- 增强型赋值:
+=,-=,*=,/=,%=
- let varOPERvalue
例如:let count+=3
自加3后自赋值
- 自增,自减:
let var+=1
let var++
let var-=1
let var–
16、逻辑运算
- true,false
1,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,第二个必须要参与运算
17、退出状态
- 进程使用退出状态来报告成功或失败
> 0 代表成功,1-255代表失败
> $? 变量保存最近的命令退出状态
- 例如:
$ ping -c1 -W1 hostdown &> /dev/null
$ echo $?
18、退出状态码
- bash自定义退出状态码
exit [n]:自定义退出状态码
注意:退出中一旦遇到exit命令,脚本会立即终止;终止退出状态取决于exit命令后面的数字
注意:如果未给脚本指定状态码,整个脚本的退出状态码取决于脚本中执行的最后一条命令的
状态码
19、条件测试
- 判断某需求是否满足,需要由测试机制来实现
专用的测试表达式徐奥由测试命令辅助完成测试过程
- 评估布尔声明,以便用在条件性执行中
> 若真,则返回0
. > 若假,则返回1
- 测试命令:
> test EXPRESSION
> [ EXPRESSION ]
> [ [ EXPRESSION ] ]
注意:EXPRESSION前后必须有空白字符
20、条件性的执行操作符
- 根据退出状态而定,命令可有条件地运行
> && 代表条件性的AND THEN
> || 代表条件性的OR ELSE
- 例如:
$ grep -q no_such_uesr /etc/passwd
| | echo ‘No such user’
No such user
$ ping -c1 -W2 station1 &> /dev/null
> && echo “station1 is up”
> || (echo ‘station1 is unreachable’ : exit1)
station1 is up
21、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”
22、bash的测试类型
-gt:是否大于
-ge:是否大于等于
-eq:是否等于
-ne:是否不等于
-lt:是否小于
-le:是否小于等于
23、bash的测试类型
- 字符串测试
==:是否等于;
> : ascii码是否大于ascii码
< : 是否小于
!=:是否不等于
=~:左侧字符串是否能够被右侧的PATTERN所匹配
注意:此表达式一般用于[[ ]]中;扩展的正则表达式
-z “STRING”: 字符串是否为空,空为真,不空为假
-n “STRING”: 字符串是否不空,不空为真,空为假
- 注意:用于字符串比较时的用到的操作数都应该是使用引号
24、文件测试
- 存在性测试
-a FILE: 同-e
-e FILE:文件存在性测试,存在为真,否则为假
- 存在性及类别测试
-b FILE: 是否存在且为块设备文件
-c FILE: 是否存在且为字符设备文件
-d FILE: 是否存在且为目录文件
-f FILE: 是否存在且为普通文件
-h FILE 或 -L FILE : 存在为符号链接文件
-p FILE: 是否存在且为命名管道文件
-S FILE: 是否存在且为套接字文件
- 文件权限测试:
-r FILE: 是否存在且可读
-w FILE:是否存在且可写
-x FILE :是否存在且可执行
- 文件特殊权限测试:
-u FILE : 是否存在且拥有suid权限
-g FILE: 是否存在且拥有sgid权限
-k FILE:是否存在且拥有sticky权限
25、组合测试条件
- 第一种方式:
COMMAND1 && COMMAND2 并且
COMMAND1 | | COMMAND2 或者
!COMMAND 非
如:[[ -r FILE ]] && [[ -w FILE ]]
- 第二种方式:
EXPRESSION1 -a EXPRESSION2 并且
EXPRWSSION1 -o EXPRESSION2 或者
!EXPRESSION
“!”最高, “-a”次之,”-o”最低。
示例:
# [ -z “$HOSTNAME” -o $HOSTNAME “== “localhost.localdmain” ] && hostname
# [ -f /bin/cat -a -x /bin/cat ] && cat /etc/fstab
26、使用read命令来接受输入
- 使用read来把输入值分配给一个或多个shell变量:
-p 指定要显示的提示
-s 静默输入
-n N指定输入的字符长度N
-d ‘字符‘ 输入结束符
-t N TIMEOUT为N秒
read 从标准输入中读取值, 给每个单词分配一个变量所有剩余单词都被分配给最后一个变
量
read -p “Enter a filename:” FILE
27、bash如何展开命令行
- 把命令行分成单个命令词
- 展开别名
- 展开大括号的声明({})
- 展开波浪符声明(·)
- 命令替换$( ) 和 “)
- 再次把命令行分成命令词
- 展开文件通配(*、?、[abc]等等)
- 准备I/O重导向 (<、>)
- 运行命令
28、防止扩展
- 反斜线()会使随后的字符按愿意解释
$ echo Your cost: $5.00
Your cost : $5.00
- 加引号来防止扩展
>单引号(’)防止所有扩展
>双引号(”)也防止所有扩展,但是一下情况例外:
>$(美元符号) — 变量扩展
>` (反引号) — 命令替换
> (反斜线) — 禁止单个字符扩展
> !( 叹号 ) — 历史命令替换
29、bash的配置文件
- 按生效范围划分,存在两类:
- 全局配置:
/etc/profile
/etc/profile.d/*.sh
/etc/bashrc
- ~/.bash_profile
- ~/.bashrc
30、shell登录两种方式
- 交互式登录:
(1) 直接通过终端输入账号密码登录;
(2)使用”su – UserName” 切换的用户
执行顺序:
/etc/profile — > /etc/profile.d/*.sh — >
~/.bash_profile — > ~/ .bashrc — > /etc/bashrc
- 非交互式登录:
(1)su UserName
(2)图形界面下打开的终端
(3)执行脚本
执行顺序:
~/ .bashrc –> /etc/bashrc –> /etc/profile.d/*.sh
31、Profile类
- 按功能划分,存在两类:
profile类和bashrc类
- profile类:为交互式登录的shell提供配置
全局: /etc/profile, /etc/profile.d/*.sh
个人 : ~/.bash_profile
功用:
(1)用于定义环境变量
(2)运行命令或脚本
32、Bashrc类
- bashrc类 :为非交互式和交互式登录的shell提供配置
全局:/etc/bashrc
个人:~/ .bashrc
功用:
(1) 定义命令别名和函数
(2) 定义本地变量
33、编辑配置文件生效
- 修改profile和bashrc文件后需生效
两种方法:
1 重新启动shell进程
2 . 或source
例:
.~/.bashrc
34、Bash 退出任务
- 保存在~/.bash_logout文件中(用户)
- 在退出登录shell时运行
- 用于
> 创建自动备份
> 清除临时文件
35、变量高级操作
- 测试变量存在性
- 字符串切片
1 ${变量:位置起点}
由指定的位置开始,截取字符串到字符串结束
eg:MYNAME=”liangchenye”
substr=${MYNAME:4}
2 ${变量: 位置起点: 长度}
eg:MYNAME=”liangchenye”
substr2=${MYNAME:4:6}
- 计算字符串长度
>${#变量名称}
>传回变量值的字符串长度
filename=”/usr/sbin/ntpd”
echo ${#filename}
PS:另外一种方法:
expr length “$filename”
- 由前面(最左边)开始,对比变量值,删除“最短相符合的字符串”
> ${变量#样式}
> filename=”/usr/sbin/ntpdate”
echo ${filename#/*/}
由前面对比,删除最长的
${变量##样式}
> filename=”/usr/sbin/ntpdate”
echo ${filename##/*/}
- 由后面对比,删最短的
>${变量%样式}
>filename=” /usr/sbin/ntpd”
> echo ${filename%/*}
由后面对比,删最长的
${变量%%样式}
domainname=”www.178Linux.com”
echo ${domainname%%.*}
- 只替换第一个对比符合的字符串
> ${变量/样式/字符串}
> name=”liangchenye”
> echo ${name/liang/wang}
- 替换全部对比符合的字符串
> ${变量//样式/替换字符串}
> name=”zhaoritianzhaoritian”
> echo ${name//zhao/ye}
- 把对比符合的字符串删除
> 只删除一个 ec
> ${变量/样式/}
> name=“liangchenye”
> echo ${name//zhao/}
36、变量操作:测试存在值及空值
- ${待测变量-默认值}
>若变量不存在,则符合判断,传回默认值
> unset myname
> echo ${myname-“fuerkang”}
- ${待测变量:=默认值}
>若变量号不存在或其值为空,则符合判断,传回默认值
> unset myneme
> echo ${myname := “fuerkang”}
37、循环判断 if
- 判断之if
>结构
>书写格式
38、循环判断 for
- 循环之for
>书写格式
> c类型
- 循环中断
> continue
> break
39、循环判断 while until
- 循环之while
>书写格式
- 循环之until
>书写格式
- while和until区别
>while为真执行后面代码段
>until 为真是停止执行
- 循环中断
>continue
>break
- while,until和for的区别
>for 可预见
> while,until不可预见
循环判断 case
- 判断之case
>书写格式
>常用使用场景
40、函数
- 函数
>定义
>调用
>作用:实现代码重用
>位置函数作为参数
41、数组
- 声明
>a=(1 2 3 4)
>a[0]=1 a[1]=2
>a=([0]=1 [1]=2 [3]=4)
- 显示数组所有元素
.>echo ${a[*]}
>echo ${a[@]}
- 显示数组所有索引
>echo ${!a[@]}
- 使用索引显示元素
>echo ${a[0]}
- 数组元素个数
>echo ${#a[@]} 或 echo ${#a[*]}