1 Shell基础
1.1 shell概述
命令行解释器: Shell 是一个命令行解释器,它可以向 Linux 内核发送请求以便运行程序,用户可以用Shell来启动、挂起、停止一些程序。
一门语言: Shell 还是一个功能相当强大的编程语言,易编写,易调试,灵活性较强。Shell时解释执行的脚本语言,在 Shell 中可以直接调用 Linux 系统命令。
1.2 Shell的分类
注意: Bourne Shell 和 C Shell 两种 shell 语法不兼容。
shell | 语法 | 家族 |
---|---|---|
Bourne Shell | Bourne | sh(兼容bash)、 ksh、 bash(linux的标准shell)、 psh |
C Shell(主要用于Unix) | C | csh、 tcsh |
Bourne Shell
历史: 从1979起就开始使用Bourne Shell
,Bourne Shell
的主文件名为sh
。
特点:功能简单,不支持历史操作。
1 | $ echo $SHELL |
C Shell
说明:C Shell主要在 BSD 版的 Unix 系统中使用,其语法和 C 语言相类似而得名。
1.1.3 子Shell
规则:
- 在一个 shell 中可以调用其它 shell,它们存在父子关系
- 子 shell 可以是一个和父 shell 不同的 shell
1.2 脚本执行方式
1.2.1 echo
语法:echo [选项] [输出内容]
选项 | 说明 |
---|---|
-e | 支持反斜线控制的字符转换 |
####控制字符列表
控制字符 | 作用 |
---|---|
\a | 输出警告音 |
\b | 退格键,也就是向左删除键 |
\n | 换行符 |
\r | 回车键 |
\t | 制表符,也就是Tab键 |
\v | 垂直制表符 |
\0nnn | 按照八进制ASCLL码表输出字符。其中0位数字零,nnn时3位八进制数 |
\xhh | 按照十六进制ASCLL码表输出字符。其中hh是两位16进制 |
\e | 为输出文本添加颜色,格式为\e[1;[色值][文本]\e[0m 。其中\e[1; 代表开始位置,\e[0m 代表关闭颜色 |
####颜色
色值(前面的可以添加# ,也可以省略) |
代表的颜色 |
---|---|
30m | 黑色 |
31m | 红色 |
32m | 绿色 |
33m | 黄色 |
34m | 蓝色 |
35m | 洋红 |
36m | 青色 |
37m | 白色 |
1 | #按照十六进制的ASCLL码输出 |
1.2.2 第一个脚本
注意:#!/bin/zsh
不应该省略(对一些简单shell省略未必要问题,但会给其他shell留下隐患)
1 |
|
1.2.3 执行方式
1.2.3.1 ./
(需要赋予权限)
1 | $ chmod +x hello.sh |
1.2.3.2 指定shell执行(不需要赋予权限)
1 | $ zsh hello.sh |
1.3 别名和快捷键
1.3.1 别名
命令生效优先级:
序号 | 命令 |
---|---|
1 | 用绝对路径或相对路径执行的命令 |
2 | 别名 |
3 | Bash的内部命令 |
4 | 按照$PATH 环境变量定义的目录查找顺序找到的第一个命令 |
1 | #查看已经生效的所有别名 |
13.2 快捷键
快捷键 | 用途 |
---|---|
ctrl+c | 强制终止当前命令 |
ctrl+l | 清屏 |
ctrl+a | 光标移动到命令行首 |
ctrl+e | 光标移动到命令行尾 |
ctrl+u | 从光标所在位置删除到行首 |
ctrl+z | 把命令放入后台 |
ctrl+r | 在历史命令中搜索 |
1.4 历史命令
1.4.1 history
注意:不推荐清空历史命令
语法:history [选项] [历史命令保存文件]
选项:
选项 | 用途 |
---|---|
-c | 清空历史命令 |
-w | 把缓存中的历史命令写入历史命令保存文件~/.bash_history |
1.4.2 历史命令的调用
- 使用上、下箭头调用以前的历史命令
- 使用
!n
重复执行第n条历史命令 - 使用
!!
重复执行上一条命令 - 使用
!字串
重复执行最后一条以该字串开头的命令
1.5 输出重定向
1.5.1 标准输入输出
设备 | 设备文件名 | 文件描述符 | 类型 |
---|---|---|---|
键盘 | /dev/stdin | 0 | 标准输入 |
显示器 | /dev/stdout | 1 | 标准输出 |
显示器 | /dev/stderr | 2 | 标准错误输出 |
1.5.2 输出重定向
注意:2>>
和2>
两边不能带空格。
1.5.3 输入重定向
wc [选项] [文件名]
:
选项:
选项 | 作用 |
---|---|
-c | 统计字节数 |
-w | 统计单词数 |
-l | 统计行数 |
1 | #行数 字数 字符数 |
1.5.4 实例
1 | #stdout和stderr |
1.6 管道符
1.6.1 命令执行的判断依据
1 | #如果存在/tmp/abc就创建/tmp/abc/hehe,否则不创建 |
1.6.2 管线命令
[命令1] [命令2]
:命令1的正确输出作为命令2 的操作对象
1 | $ ls -al /etc | less |
1.7 通配符
1 | $ ls index* |
1.8 Bash中的其他特殊符号
2 Bash变量与变量分类
2.1 Bash变量与变量分类
2.1.1 变量命名规则
- 变量名必须以字母或下划线打头,名字中间只能由字母、数字和下划线组成
- 变量名的长度不得超过255个字符
- 变量名在有效范围内必须是唯一的
- 在Bash中,变量的默认类型都是字符串型
2.1.2 变量分类
注意:bash中的所有变量都是字符串
分类 | 用途 |
---|---|
用户自定义变量 | 自己定义的变量 |
环境变量 | 主要保存的是和操作系统环境相关的数据。变量可以自定义,但是对系统生效的环境变量名和变量作用是固定的 |
位置参数变量 | 主要用来向脚本中传递参数或数据,变量名不能自定义,变量作用是固定的 |
预定义变量 | 是Bash中已经定义好的变量,变量名不能自定义,变量作用也是固定的 |
2.2 用户自定义变量
2.2.1 定义变量
语法:变量名=变量值
注意:
- 变量值存在空格时需要用
""
=
左右两侧不能有空格
2.2.2 变量调用
语法:$变量名
1 | $ echo $x |
2.2.3 变量叠加
用途:通过为变量追加字符串获得新的字符串
1 | x=123 |
2.2.4 set
用途:查看系统中所有已经生效的变量
选项:
-u | 如果设定此选项,调用未声明变量时会报错(默认无任何提示) |
---|---|
2.2.5 变量删除
语法:unset 变量名
特点:不仅仅清空变量的值,会使变量不再存在
注意:变量名
不需要在前面添加$
2.3 bash环境变量
环境变量与用户自定义变量的区别?
- 用户自定义变量只在当前的shell中生效
- 环境变量在当前Shell和这个Shell的所有子Shell中生效
1 | $ pstree | grep bash |
2.3.1 声明环境变量
语法:export 变量名=变量值
查看环境变量:env
2.3.2 删除环境变量
语法:unset $环境变量名
注意:
- 无法在子shell中删除父shell中声明的环境变量
- 推荐环境变量名使用大写来定义(因为所有命令都是小写)
2.3.3 常见环境变量
环境变量名 | 用途 |
---|---|
HOSTNAME | 主机名 |
SHELL | 当前的shell |
TERM | 终端环境 |
HISIZE | 历史命令条数 |
SSH_CLIENT | 当前操作环境是用ssh连接的,这里记录客户端ip |
SSH_TTY | ssh连接的终端是pts/1 |
USER | 当情登陆的用户 |
PATH | 系统查找命令的路径 |
PS1 | 命令提示符设置 |
PS2 | 长命令使用\ 换行后行首的标志符 |
PATH环境变量
用途:系统查找命令的路径,非常重要
查看:echo $PATH
追加(变量叠加):PATH="$PATH":/root/sh
PS1环境变量
项目 | 用途 |
---|---|
\d | 显示日期,格式为“星期 月 日” |
\H | 显示完整的主机名。如默认主机名”localhost.localdomain” |
\t | 显示24小时制时间,格式为”HH:MM:SS” |
\A | 显示24小时制时间,格式为“HH:MM” |
\u | 显示当前用户名 |
\w | 显示当前所在目录的完整名称 |
\W | 显示当前所在目录的最后一个目录 |
\$ | 提示符。root用户为”#”,普通用户为”$” |
2.4 bash语系变量
2.4.1 locale
locale
:查询当前系统的语系
相关环境变量 | 含义 | 特点 |
---|---|---|
LANG | 定义系统主语系的变量 | 当前生效的语系 |
LC_ALL | 定义整体语系的变量 | 默认整体的语系 |
系统默认语系:/etc/sysconfig/i18n
1 | #查看所有支持的语系 |
2.4.2 Linux中文支持
正确安装中文字体后的3种情况:
- 如果有图形界面,可以正确支持中文显示
- 如果使用第三方远程工具,只要语系设定正确,可以支持中文显示
- 如果纯字符界面,必须使用第三方插件(如zhcon等)
2.5 位置参数变量
1 | $ vim sum.sh |
2.5.1 $*
和$@
的区别
1 | $ vim test.sh |
2.6 预定义变量
1 | $ echo $$ |
2.6.1 接收键盘输入
命令:read [选项] [变量名]
选项 | 用途 |
---|---|
-p “提示信息” | 在等待read输入时,输出提示信息 |
-t 秒数 | read命令会一直等待用户输入,使用此选项可以制定等待时间 |
-n 字符数 | read命令只接受指定的字符数就会执行 |
-s | 隐藏输入的数据,适用于机密信息的输入 |
1 |
|
3 运算符
3.1 课程概述及declare命令
shell变量的缺点
- 弱类型
- 默认字符串类型
3.1.1 declare声明变量类型
语法:declare [+/-] [选项] 变量名
选项 | 用途 |
---|---|
- | 给变量设定类型属性 |
+ | 取消变量的类型属性 |
-a | 将变量声明为数组型 |
-i | 将变量声明为整型 |
-x | 将变量声明为环境变量 |
-r | 将变量声明为只读变量 |
-p | 显示指定变量被声明的类型 |
1 | #给变量aa和bb赋值 |
3.1.2 声明数组变量
注意:只要在数组名后使用了[下标]
,shell会自动将该变量作为数组类型
1 | #为数组赋值,declare的过程可以省略 |
3.1.3 声明环境变量
说明:export
声明环境变量,底层使用的是declare -x
1 | $ export aa=11 |
3.1.4 只读变量
特点:
- 临时生效
- 无法取消类型声明
- 无法删除
1 | #声明只读变量 |
3.2 数值运算方法
两种方式
- 方式一:
declare
(有点麻烦)
1 | aa=1 |
- 方式二:
expr
或let
数值运算工具(也麻烦)
1 | aa=1 |
- 方式三:
$((运算式))
(推荐)或$[运算式]
(方便)
1 | $ aa=11 |
3.3 运算符
优先级递减
3.4 变量测试
优点:语法简单,效率高
缺点: 理解困难
1 | $ unset y |
4 条件判断与流程控制
4.1 条件判断式与语句
两种判断格式
test -e /root/install.log
[ -e /root/install.log ]
4.1.1 概述(略)
4.1.2 按照文件类型判断
流程控制语句
- 条件判断式
- 单分支if语句
- 双分支if语句
- 多分支if语句
- case语句
- for循环
- while循环和util循环
1 | $ [ -e ./sum.sh ] && echo yes || echo no |
4.1.3 按文件权限判断
4.1.4 两个文件之间的比较
1 | #创建硬链接 |
4.1.5 两个整数之间的比较
1 | $ [ 23 -ge 22 ] && echo yes || echo no |
4.1.6 字符串的判断
注意:
- 判断字符串是否相等也可以使用
=
代替==
,但容易和赋值操作混淆,因此不推荐。 - 用
$变量
访问变量如果出现异常可以尝试在外面加上"
- 比较数字大小一般也可以用比较字串来替代
1 | $ name=gui |
4.1.7 多重条件判断
1 | $ a=22 |
4.2 单分支if语句
4.2.1 概述
shell的语法结构和大多数语言都不同
学习小脚本实例的好处
- 掌握语法结构
- 了解shell的作用
- 分析编程思想
建立编程思想的方法
- 熟悉Linux基本命令、规范、语法及shell语法
- 当遇到实际需求时,应用所学知识
4.2.2 单分支if语句
4.2.2.1 需要注意的几个地方
if
语句使用fi
结尾,和一般语言使用大括号结尾不同[ 条件判断式 ]
就是使用test
命令判断,所以中括号和条件判断式之间必须有空格then
后面跟符号条件之后执行的程序,可以放在[]
之后,用;
分割。也可以换行写入,就不需要;
了
4.2.2.2 语法
方式一
1 | if [ 条件判断式 ];then |
方式二
1 | if [ 条件判断式 ] |
4.2.2.3 案例:判断当前用户是否是root
注意:使用whoami
判断用户身份在su root
情况下会误认为当前用户还是却换为root之前的用户,因此使用env
更可靠。
1 |
|
4.2.3 案例:判断分区使用率
1 |
|
4.3 双分支if语句
语法
1 | if [ 条件判断式 ] |
4.3.1 判断输入的是否是一个目录
1 |
|
4.3.2~4.3.3 判断Apache服务是否启动
注意:脚本名中不要包含httpd
1 |
|
4.4 多分支if条件语句
4.4.1 简介
语法
1 | if [ 条件判断式1 ] |
4.4.2 例:计算器
1 |
|
4.4.2 例:判断用户输入的是什么文件
注意:exit
可以终止后面的判断
1 |
|
4.5 多分支case语句
简介:case语句和if...elif...else
语句一样都是多分支条件语句,不过和if多分支条件语句不同的是,case语句只能判断一种条件关系,而if语句可以判断多种条件关系。
语法
1 | case $变量名 in |
1 |
|
4.6 for循环
语法
- 语法1
1 | for 变量 in 值1 值2 值3 ... |
- 语法2
1 | for((初始值;循环控制条件;变量变化)) |
4.6.1 for循环
1 |
|
4.6.2 例:批量添加删除指定数量的用户
注意:不支持++
--
等运算
1 |
|
4.7 while循环和unit循环
4.7.1 while循环
简介:while
循环是不定循环,也称作条件循环。只要条件判定式成立,循环就会一直继续,指导条件判定式不成立,循环才会停止。这就和for
的固定循环不太一样了。
语法:
1 | while [ 条件判定式 ] |
1 |
|
4.7.2 until循环
简介:until
循环,和while
循环相反,until
循环时只要条件判断式不成立则进行循环,并执行循环程序。一旦循环条件成立,则终止循环。
语法:
1 | until [ 条件判定式 ] |
1 |
|