1.Shell概述
1.1什么是Shell
Shell是一个应用程序, 它连接了用户和Linux内核,让用户更加高效, 安全, 低成本地使用Linux内核
1.2shell的分类
Shell的主要语法类型有Bourne和C, 这两种语法彼此不兼容. Bourne家族主要包括sh, ksh, psh, zsh; C家族主要包括: csh, tcsh
我们可以通过/etc/shells文件来查询Linux支持的Shell
2.Shell脚本的执行方式
2.1echo
echo [选项] [输出内容]
选型:
-e: 支持反斜线控制的字符转换
-n: 取消输出行末的黄行符号
在echo命令中如果使用了"-e"选项, 则可以支持控制字符
控制字符 | 作用 |
---|---|
\\ | 输入\本身 |
\a | 输出警告音 |
\n | 换行符 |
\r | 回车键 |
\t | 制表符, 也就是Tab键 |
echo还能输出颜色
2.2Shell脚本的执行
vim hello.sh
(注意少个")
这个一个打印"nihao woshiszx"的一个脚本.
Shell脚本写好了, 那么这个脚本该如何运行呢
- 赋予执行权限, 直接运行
- 通过调用Bash执行脚本
3.Bash的基本功能
3.1历史命令
1)历史命令的查看
history [选项] [历史命令保存位置]
选项:
-c: 清空历史命令
-w: 把缓存中的历史命令保存到文件中
历史命令是保存在~/.bash_history文件, 我们使用history命令查看的历史命令和~/.bash_history文件中保存的历史命令不同的. 那是因为当前登录操作的命令并没有直接写入~/.bash_history文件, 而是保存在缓存当中的. 需要等当前用户注销后, 缓存中的命令才会写入文件中. 如果我们需要把内存中的命令直接写入文件中, 我们需要加上-w选项
2)历史命令的调用
- 使用上下箭头调用之前的命令
- 使用!n重复执行第n条历史命令
- 使用!!重复执行上一条命令
- 使用"!字符串"重复执行最后一条以该字串开头的命令
- 使用!$重复上一条命令的最后一个参数
3.2命令于文件的补全
3.3命令别名
alias
alias 别名='原命令'
为了让这个别名永久生效, 可以把别名写入环境变量配置文件"~/.bashrc"
3.4Bash常用
快捷键 | 作用 |
---|---|
ctrl + A | 把光标移动到命令行开头 |
ctrl + E | 把光标移动到命令行结尾 |
ctrl + C | 强制终止当前命令 |
ctrl + L | 清屏 |
ctrl + U | 删除或剪切光标之前的命令 |
ctrl + Y | 粘贴ctrl + U剪切的内容 |
ctrl + R | 在历史命令中搜索 |
ctrl + D | 退出当前终端 |
ctrl + Z | 暂停, 并放入后台 |
3.5输入输出重定向
1)Bash的标准输入输出
设备 | 设备名 | 文件描述符 | 类型 |
---|---|---|---|
键盘 | /dev/stdin | 0 | 标准输入 |
显示器 | /dev/stdout | 1 | 标准输出 |
显示器 | /dev/stderr | 2 | 标准错误输出 |
2)输出重定向
类型 | 符号 | 作用 |
---|---|---|
标准输出重定向 | 命令 > 文件 | 以覆盖的方式, 把命令的正确输出输出到指定的文件或设备中 |
命令 >> 文件 | 以追加的方式, 把命令的正确输出输出到指定的文件或设备中 | |
标准错误输出重定向 | 错误命令 2>文件 | 以覆盖的方式, 把命令的错误输出输出到指定的文件或设备中 |
错误命令 2>>文件 | 以追加的方式, 把命令的错误输出输出到指定的文件或设备中 | |
正确输出和错误输出同时保存 | 命令 > 文件 2>&1 | 以覆盖的方式, 把命令的正确输出和错误输出都保存在同一个文件中 |
命令 >> 文件 2>&1 | 以追加的方式, 把命令的正确输出输出到指定的文件或设备中 | |
命令 &>文件 | 以覆盖的方式, 把命令的正确输出输出到指定的文件或设备中 | |
命令 &>> 文件 | 以追加的方式, 把命令的正确输出输出到指定的文件或设备中 | |
命令>>文件1 2>>文件2 | 把正确的命令追加到文件1中, 把错误的输出追加到文件2中 |
3)输入重定向
wc [选项] [文件名]
选项:
-c: 统计字节数
-w: 统计单词数
-l: 统计行数
3.6多命令顺序执行
多命令执行符 | 格式 | 作用 |
---|---|---|
; | 命令1 ; 命令2 | 多个命令顺序执行, 命令之间没有任何逻辑联系 |
&& | 命令1 && 命令2 | 当命令1正确的时候, 命令2才会执行 当命令1错误的时候, 命令2不会执行 |
|| | 命令1 || 命令2 | 当命令1执行错误的时候, 命令2才会执行 当命令1执行正确的时候, 命令2不会执行 |
3.9Bash中其他特殊符号
符号 | 作用 |
---|---|
' ' | 单引号. 在单引号中所有特殊符号, 如"$' 和 ` (反引号)都没有特殊含义 |
" " | 双引号. 在双引号中特殊符号都没有特殊含义, 但是"$", "`"(反引号)和"\"是例外, 拥有"调节变量", "引用命令", "转义符"的特殊含义 |
` ` | 反引号. 反引号括起来的内容都是系统命令, 在Bash中会先执行它. 和$()作用一样 |
$() | 和反引号作用一样, 用来引用系统命令 |
() | 用于遗传命令执行时, ()中的命令会在子Shell中执行 |
{} | 用户一串命令执行时, {}中的命令会在当前Shell中执行. 也可以用于变量变形和替换 |
[] | 用于变量的测试. 重点很多以后讲 |
# | 在Shell脚本中, #开头的行代表注释 |
$ | 用于调用变量的值, 比如需要调用变量name的值, 需要使用$name的方式 |
\ | 转义符 |
1)单引号和双引号
2)反引号
3)小括号, 中括号和大括号
在介绍小括号和大括号的区别之前, 我们先要介绍一个概念, 那就是父Shell和子Shell, 也就是父Shell和子Shell. 在我们的Bash中, 可以调用信息Bash, 比如
知道了父Shell和子Shell, 我们解释一下小括号和大括号的区别. 如果是用于一串命令的执行, 那么小括号和大括号的主要区别在于:
- ()执行一串命令时, 需要重新开一个子shell进行执行
- {}执行遗传命令时, 是在当前shell执行
- ()和{}都是一串命令放在括号里面, 并且命令之间用 ; 隔开
- ()最后一个命令可以不用分号
- {}最后一个命令要用分号
- {}的第一个命令和左括号之间必须要有一个空格
- ()里的各命令不必和空格有括号
- ()和{}中括号里面的某个命令的重定向只影响该命令, 但是括号外的重定向则影响到括号里的所有命令
[解释]
我们在父Shell中, 创建变量name赋值sc, 然后我们在子shell(子shell中的变量和父Shell中的变量是互不影响的), 然后子Shell中创建变量并且输出, 当执行完()中的命令, 会自动退出子Shell, 然后继续父Shell的命令, 在父Shell中, 输入name的值, 是sc
4.Bash的变量和运算符
4.1什么变量
在定义变量时, 有一下规则需要遵守:
- 变量名臣可以由字母, 数字和下划线组成, 但是不能以数字开头. 如果变量名是"2name", 则是错误的
- 在Bash中, 变量的默认类型都是字符串型, 如果是进行数值运算, 则必须指定变量类型为数值型
- 变量用等号连接值, 等号左右两侧不能有空格
- 变量的值如果有空格, 需要使用单引号或双引号
- 在变量的值中, 可以使用 \ 转义符
- 在变量的值中, 可以使用 \ 转义符
- 如果需要增加变量的值, 那么可以进行变量值的叠加, 形式例如"$变量名"新增内容, 或者是${变量名}新增内容
- 如果是把命令的结构作为变量值赋予变量, 则需要使用反引号或$()包含命令
- 环境变量名建议大写, 便于区分
4.2变量的分类
- 用户自定义变量: 这种变量是最常见的变量, 是由用户定义的变量名和变量值
- 环境变量: 这种变量中主要保存的是和系统操作环境中相关的数据, 比如当前登录的用户, 用户的家目录, 命令的提示符等. 环境变量的变量名可以自由定义, 但是一般对操作系统其作用的环境变量的变量名是系统预先设定好的
- 位置参数变量: 这种变量主要用来想脚本挡住传递参数或者数据的, 变量名不能自定义, 变量作用是固定的
- 预定义变量: 是Bash中已经定义好的变量, 变量名不能自定义, 变量作用也是固定的
4.3用户定义变量
1)定义变量
2name=sc # 错误, 不能以数字开头
name = sc # 错误, =两边不能有空格
name=ni hao # 值如果有空格, 要用引号
2)变量调用
3)变量查看
set [选项]
选项:
-u: 如果设定此选项, 调用未声明变量是会报错(如果没有-u, 并调用不存在的变量, 不会有任何提示
-x: 如果谁当此选项, 在命令执行之前, 会把命令先输出一次
4)删除变量
4.4环境变量
1)环境变量设置
export age="18" # 自定义的环境变量在父Shell和子Shell中都可以查询到
2)环境变量的查询和删除
env命令和set命令的区别是, set命令可以查看所有变量, 而env命令只能查看环境变量
3)系统默认的环境变量
我们可以查看使用env命令查看环境变量, 下面介绍一下几个比较重要的环境变量
- PATH: 系统查找命令的路径
先查询下PATH环境变量的值
PATH变量的值使用":"分割路径, 这些路径就是系统查找命令的路径. 也就是当我们输入一个程序名时, 没有吸入路径系统就会到PATH变量定义的路径中去寻找, 是否有可以执行的程序. 比如我们输入"ls", 没有写路径, 系统就会从PATH变量中, 找到相应的目录, 在相应的目录中进行查找命令, 知道所有在PATH下的目录执行完, 或找到命令为止
如果我们将自己写的程序的目录写入PATH中, 我们可以使用文件名直接调用. 如果我们修改环境变量, 只是临时生效, 我们需要修改相应的配置文件才能永久生效
- PS1: 命令提示符设置
PS1是一个有意思的变量, 是用来定义命令行的提示符的, 可以按照我们自己的需求来定义自己喜欢的提示符. PS1可以支持以下这些选项:
\d: 显示日期, 格式为"星期 月 日"
\H: 显示完整的主机名
\h: 显示简写的主机名, 默认是localhost
\t: 显示24小时制时间, 格式为"HH:MM:SS"
\T: 显示12小时制时间, 格式为"HH:MM:SS"
\A: 显示24小时制时间, 格式为"HH:MM"
\@: 显示12小时制时间, 格式为"HH:MM am/pm"
\u: 显示显示当前用户名
\v: 显示Bash的版本信息
\w: 显示当前所在目录的完整名称
\W: 显示当前目录的最后一个目录
\#: 执行的第几个命令
\$: 提示符, 如果是超级用户提示符是#, 如果是普通用户提示符是$
我们查看一下PS1默认值:
如果我们需要修改PS1的值, 我们要使用单引号, 否则不生效
- LANG
LANG变量定义了Linux系统的主语系环境, 我们看一下这个变量的默认值:
4.5位置参数变量
位置参数变量 | 作用 |
---|---|
$n | n为数字, $0代表命令本身, $1-$9代表第一到第9个参数, 10个以上的参数需要使用大括号表示, 如${10} |
$* | 这个变量代表命令行中所有参数, $*是把所有的参数看成一个整体 |
$@ | 这个变量也代表命令行中所有的参数, 不过$@把每个参数区分对待 |
$# | 这个变量代表命令行中所有参数的个数 |
我们设计一个加法程序
我们了解了$n是怎么使用的, 我们下面看看$*和$@是如何使用吧
4.6预定义变量
预定义变量 | 作用 |
---|---|
$? | 最后一次执行的命令的返回状态. 如果这个变量是0, 证明上一条命令正确执行; 如果这个变量的值是非0, 则证明上一个命令执行不正确 |
$$ | 当前进程的程序号(PID) |
$! | 后台运行的最后一个进程的进程号(PID) |
$?
&& 和 &!
4.7接收键盘输入
read [选项] [变量名]
选项:
-p "提示信息": 在等待read输入时, 输出提示信息
-t 秒数: read命令会一直顶戴用户输入, 使用此选项限制时间
-n 字符数: read命令只接受指定的字符数, 就会执行
-s: 隐藏输入的数据, 适用于机密信息的输入
这个相比于位置参数的话更加的合理, 拥有相应的提示, 可以给使用者提供指导
4.8Shell的运算符
1)数值运算的方法
如果我们需要进行数值运算, 可以采用一下三种方式:
方法一: 使用declare声明变量类型
既然所有变量的默认类型是字符串类型, 那么只要我们把变量声明为证书型不就可以运算了吗?使用declare命令就可以实现声明变量的类型. 命令如下:
declare [+/-][选项] 变量名
选项:
-: 给变量设置类型属性
+: 取消变量的类型属性
-a: 将变量声明为数组型
-i: 将变量声明为整数型
-r: 将变量声明为只读类型. 注意, 一旦设置为只读类型变量, 既不能修改变量的值, 也不能删除变量, 甚至不能通过+r取消只读属性
-x: 将变量声明为环境变量
-p: 显示指定变量的被声明的类型
例子1: 数值运算
例子2: 数组变量类型
所谓数组, 就是相同的数据类型的元素按照一定顺序排列的集合, 就是把有限个类型相同的变量用一个名字命名, 然后用编号区分他们的变量的集合, 这个名字称为数组名, 编号称为下标.
注意数组的小标从0开始, 在调用数组时, 需要使用${数组[小标]}的方式来读取, "变量[下标]的格式, 这个变量会被系统认为是数组型, 不用额外声明
例子3: 环境变量
我们使用declare命令把变量声明为环境变量, 和export命令的作用一样
例子4: 只读属性
注意一旦变量设定了只读属性, 那么这个变量既不能修改又不能删除, 也不能修改变量的值, 甚至不能使用+r选项取消只读属性. 我们只能通过重启或者重新登录才能删除变量
例子5: 查询变量属性和取消变量属性
方法二:使用expr或let数值运算工具
要想进行数值运算的第二种方法是使用expr命令, 这种命令没有declare命令复杂,命令如下:
注意: + 左右两边必须有空格(上图)
方法三: 使用 $((运算式)) 或 $[运算式] 方式运算
2)shell常用的运算符
优先级 | 运算符 | 说明 |
---|---|---|
13 | + - | 单目正负 |
12 | ! ~ | 逻辑非, 按位取反或补码 |
11 | * / % | 乘除余 |
10 | + - | 加减 |
9 | << >> | 按照左移, 按位右移 |
8 | <=, >=, >, < | 小于等于, 大于等于, 大于, 小于 |
7 | ==, != | 等于, 不等于 |
6 | & | 按位与 |
5 | ^ | 按位异或 |
4 | | | 按位或 |
3 | && | 逻辑与 |
2 | || | 逻辑或 |
1 | =, +=, -=, *=, /=, %=, &=, ^=, |=, <<=, >>= | 赋值, 运算然后赋值 |
优先级高的, 最先运算
4.9变量的测试与内容置换
解析: 我们删除一个变量a, 然后查询a的值是空, 然后我们定义一个变量a并赋值为空, 然后输出显示空. 两个空, 在我们编写程序的时候不知道是没有这个变量, 还是值为空, 这个时候, 需要我们学习以下的知识进行区分
变量置换方式 | 变量y没有设置 | 变量y为空值 | 变量y设置值 |
---|---|---|---|
x=${y-新值} | x=新值 | x为空 | x=$y |
(注: 有很多变量测试与替换的方法, 我们掌握一种, 其他的见到认识即可)
5.环境变量配置文件
5.1source
source 配置文件
. 配置文件
5.2环境变量配置文件
1)登录时生效的环境变量配置文件
在Linux系统登录时主要生效的环境变量配置文件有以下5种:
- /etc/profile
- /etc/profile.d/*.sh
- ~/.bash_profile
- ~/.bashrc
- /etc/bashrc
[正常登录流程]
[错误登录流程]
文件一: 用户登录过程先调用/etc/profile文件
在这个环境变量配置文件中会定义这些默认环境变量:
- USER变量: 根据登录用户, 给这个变量赋值
- LOGNAME变量: 根绝USER变量的值, 给这个变量赋值
- MAIL变量: 根据登录用户, 定义用户的邮箱为/var/spool/mail/用户名
- PATH变量: 根据登录用户的UID是否为0, 判断PATH变量是否包含/sbin, /usr/sbin和/usr/local/sbin这三个系统命令目录
- HOSTNAME: 更改主机名, 给这个变量赋值
- HISTSIZE变量: 定义历史命令的保存条数
- umash: 定义umash默认权限.
- 调用/etc/profile.d/*.sh文件
- 由/etc/profile文件调用/etc/profile.d/*.sh文件(这里面包含默认语系配置文件
- 由/etc/profile文件调用~/.bash_profile文件(这个文件有调用了后面的文件, 同时在PATH变量后, 追加了":$home/bin"这个目录. 我们在这个目录下创建相应的shell脚本能够直接运行)
- 由~/.bash_profile文件调用了~/.bashrc文件(这个文件调用了后面的文件, 同时定义了默认别名
- 由~/.bashrc调用了/etc/bashrc文件(这个文件定义了PS1变量, 同时当用户没有登录时会定义umash变量, PATH变量, 调用下面的文件)
这样这五个环境变量配置文件会被依次调用, 那么如果是我们自己定义的环境变量应当放在哪个文件中呢? 如果你的修改是打算对所有用户生效的, 那么可以放入/etc/profile环境变量配置文件; 如果你的修改只是自己用, 那么可以放入~/.bash_profile或~/.bashrc这两个配置文件的任意一个
2)注销时生效的环境变量配置文件
在用户退出登录时, 指挥调用一个环境变量配置文件, 就是~/.bash_logout. 这个文件默认没有写入任何内容, 可以如果希望在退出登录的时候做一些事情, 比如清楚历史命令, 备份某些数据, 就可以在这些文件中写入相应的内容
3)其他配置文件
还有一些环境变量配置文件, 最常见的就是~/bash_history, 也就是历史命令保存文件