一 ~ 四章
五、shell 编程
5.1、shell 概述
5.1.1 shell 是什么
-
Shell是一个命令行解释器,它为用户提供了一个向Linux内核发送请求以便运行程序的界面系统级程序,用户可以用Shell来启动、挂起、停止甚至是编写一些程序。
-
Shell还是一个功能相当强大的编程语言,易编写,易调试,灵活性较强。Shell是解释执行的脚本语言,在Shell中可以直接调用Linux系统命令。
5.1.2 shell 的分类
-
Bourne Shell:从1979起Unix就开始使用Bourne Shell,Bourne Shell的主文件名为sh。
-
C Shell: C Shell主要在BSD版的Unix系统中使用,其语法和C语言相类似而得名
-
Shell的两种主要语法类型有Bourne和C,这两种语法彼此不兼容。Bourne家族主要包括sh、ksh、Bash、psh、zsh;C家族主要包括:csh、tcsh
-
Bash: Bash与sh兼容,现在使用的Linux 就是使用Bash作为用户的基本Shell。
5.2、shell 脚本的执行方式
5.2.1 echo 输出命令
命令名称:echo
echo [选项] [输出内容]
选项: -e: 支持反斜线控制的字符转换
控制字符 | 作用 |
---|---|
\ | 输出\ |
\a | 输出警告音 |
\b | 退格键,向左删除键 |
\c | 取消输出行末的换行符,和“-n”选项一致 |
\e | ESCAPE键 |
\f | 换页符 |
\n | 换行符 |
\r | 回车键 |
\t | 制表符,Tab键 |
\v | 直制表符 |
\0nnn | 按照八进制ASCII码表输出字符,0为数字零,nnn为三位八进制数 |
\xhh | 按照十六进制ASCII码表输出字符,其中hh是两位十六进制数 |
示例:
[root@zhangRabbitMQ zhang]# echo -e "ab\bc"
ac
[root@zhangRabbitMQ zhang]# echo -e "a\tb\tc\nd\te\tf"
a b c
d e f
5.2.2 编写脚本
[root@zhangRabbitMQ zhang]# vi /tmp/hello.sh
#!/bin/bash
echo "helloword"
5.2.3 执行脚本
[root@zhangRabbitMQ zhang]# chmod 755 /tmp/hello.sh
[root@zhangRabbitMQ zhang]# /tmp/hello.sh
helloword
5.3、Bash的基本功能
5.3.1 历史命令与命令补全
历史命令:history
命令名称:history
[root@localhost ~]# history [选项] [历史命令保存文件]
选项:
-c: 清空历史命令
-w: 把缓存中的历史命令写入历史命令保存文件
~/.bash_history
- 历史命令默认会保存1000条,可以在环境变量配置文件/etc/profile中进行修改
历史命令的调用
-
使用上、下箭头调用以前的历史命令
-
使用“!n”重复执行第n条历史命令
-
使用“!!”重复执行上一条命令
-
使用“!字串”重复执行最后一条以该字串开头的命令
命令与文件补全
- 在Bash中,命令与文件补全是非常方便与常用的功能,我们只要在输入命令或文件时,按“Tab”键就会自动进行补全
5.3.2 命名别名与常用快捷键
命令别名
[root@localhost ~]# alias 别名='原命令'
#设定命令别名
[root@localhost ~]# alias
#查询命令别名
命令的执行顺序
-
- 第一顺位执行用绝对路径或相对路径执行的命令。
-
- 第二顺位执行别名。
-
- 第三顺位执行Bash的内部命令。
-
- 第四顺位执行按照$PATH环境变量定义的目录查找顺序找到的第一个命令。
让别名永久生效,需要把配置写入配置文件/root/.bashrc中
Bash 常用快捷键
5.3.3 输入输出重定向
同时输出正确和错误
5.3.4 多命令执行与管道符
多命令顺序执行
管道符:|
命令名称:|
# 语法,将命令1的输出结果,作为命令2的输入: 命令1 | 命令2
命令格式:
[root@localhost ~]# 命令1 | 命令2
#命令1的正确输出作为命令2的操作对象
例子:
[root@localhost ~]# ll -a /etc/ | more
[root@localhost ~]# netstat -an | grep "ESTABLISHED"
查找aries用户:cat /etc/passwd | grep -n “baizhi”
查找aries组:cat /etc/group | grep -n “baizhi”
查找sshd进程:ps -aux | grep sshd
5.3.5 通配符与其他特殊符号
通配符
其他特殊符号
5.4、Bash 变量
5.4.1 用户自定义变量
什么是变量
- 变量是计算机内存的单元,其中存放的值可以改变。当Shell脚本需要保存一些信息时,如一个文件名或是一个数字,就把它存放在一个变量中。每个变量有一个名字,所以很容易引用它。使用变量可以保存有用信息,使系统获知用户相关设置,变量也可以用于保存暂时信息。
变量设置规则
-
变量名称可以由字母、数字和下划线组成,但是不能以数字开头。如果变量名是“2name”则是错误的。
-
在Bash中,变量的默认类型都是字符串型,如果要进行数值运算,则必修指定变量类型为数值型。
-
变量用等号连接值,等号左右两侧不能有空格。
-
变量的值如果有空格,需要使用单引号或双引号包括。
-
在变量的值中,可以使用“\”转义符。
-
如果需要增加变量的值,那么可以进行变量值的叠加。不过变量需要用双引号包含“ 变量名”或用 变量名”或用 变量名”或用{变量名}包含。
-
如果是把命令的结果作为变量值赋予变量,则需要使用反引号或$()包含命令。
-
环境变量名建议大写,便于区分。
变量分类
-
用户自定义变量 环境变量:这种变量中主要保存的是和系统操作环境相关的数据。
-
位置参数变量:这种变量主要是用来向脚本当中传递参数或数据的,变量名不能自定义,变量作用是固定的。
-
预定义变量:是Bash中已经定义好的变量,变量名不能自定义,变量作用也是固定的。
本地变量
- 变量定义
[root@localhost ~]# name="shen chao"
- 变量叠加
[root@localhost ~]# aa=123
[root@localhost ~]# aa="$aa"456
[root@localhost ~]# aa=${aa}789
- 变量调用
[root@localhost ~]# echo $name
- 变量查看
[root@localhost ~]# set
查看当前系统全部变量
- 变量删除
[root@localhost ~]# unset name
5.4.2 环境变量
环境变量是什么
- 用户自定义变量只在当前的Shell中生效,而环境变量会在当前Shell和这个Shell的所有子Shell当中生效。如果把环境变量写入相应的配置文件,那么这个环境变量就会在所有的Shell中生效
设置环境变量
export 变量名=变量值
申明变量
env
查询变量
unset 变量名
删除变量
系统常见环境变量
PATH:系统查找命令的路径
[root@localhost ~]# echo $PATH /usr/lib/qt-3.3/bin:/usr/local/sbin:/usr/local/bin: /sbin:/bin:/usr/sbin:/usr/bin:/root/bin
PATH="$PATH":/root/sh
PATH变量叠加
PS1:定义系统提示符的变量
\d:显示日期,格式为“星期 月 日”
\h:显示简写主机名。如默认主机名“localhost”
\t:显示24小时制时间,格式为“HH:MM:SS”
\T:显示12小时制时间,格式为“HH:MM:SS”
\A:显示24小时制时间,格式为“HH:MM”
\u:显示当前用户名
\w:显示当前所在目录的完整名称
\W:显示当前所在目录的最后一个目录
\#:执行的第几个命令
\$:提示符。如果是root用户会显示提示符为“#”,如果是普通用户会显示提示符为“$”
示例:
[root@localhost ~]# PS1='[\u@\t \w]\$ '
[root@04:50:08 /usr/local/src]#PS1='[\u@\@ \h \# \W]\$‘
[root@04:53 上午 localhost 31 src]#PS1='[\u@\h \W]\$ '
5.4.3 位置参数变量
位置参数变量
示例:
#!/bin/bash
num1=$1
num2=$2
sum=$(( $num1 + $num2))
#变量sum的和是num1加num2
echo $sum
#打印变量sum的值
[root@zhangRabbitMQ zhang]# /tmp/sum.sh 1 2
3
5.4.4 预定义变量
5.5、Bash运算符
5.5.1 数值运算与运算符
declare声明变量类型
数值运算
[root@localhost ~]# declare [+/-][选项] 变量名
选项:
-: 给变量设定类型属性
+: 取消变量的类型属性
-i: 将变量声明为整数型(integer)
-x: 将变量声明为环境变量
-p: 显示指定变量的被声明的类型
方法1:
[root@localhost ~]# aa=11
[root@localhost ~]# bb=22 #给变量aa和bb赋值
[root@localhost ~]# declare -i cc=$aa+$bb
方法2:expr或let数值运算工具
[root@localhost ~]# aa=11
[root@localhost ~]# bb=22
#给变量aa和变量bb赋值
[root@localhost ~]# dd=$(expr $aa + $bb)
#dd的值是aa和bb的和。注意“+”号左右两侧必须有空格
方法3:“$((运算式))”或“$[运算式]” (推荐)
[root@localhost ~]# aa=11
[root@localhost ~]# bb=22
[root@localhost ~]# ff=$(( $aa+$bb ))
[root@localhost ~]# gg=$[ $aa+$bb ]
5.6、环境变量配置文件
5.6.1 配置文件简介
source命令
source命令通常用于保留、更改当前shell中的环境变量。
[root@localhost ~]# source 配置文件
或
[root@localhost ~]# . 配置文件
环境变量配置文件简介
-
环境变量配置文件中主要是定义对系统的操作环境生效的系统默认环境变量,比如PATH、HISTSIZE、PS1、HOSTNAME等默认环境变量。
-
/etc/profile
-
/etc/profile.d/*.sh
-
~/.bash_profile
-
~/.bashrc
-
/etc/bashrc
5.6.2 环境变量配置文件作用
配置文件列表如下:
-
/etc/profile
-
/etc/profile.d/*.sh
-
~/.bash_profile
-
~/.bashrc
-
/etc/bashrc
tips:/etc 目录下的对所有用户都生效
~/.bash_profile 和 ~/.bashrc -> 每个用户自己的配置文件,只对用户生效。
配置文件读取顺序
上图从左到右如果有叠加。后面的命令会覆盖前面的命令。
/etc/profile的作用:
-
USER变量:
-
LOGNAME变量:
-
MAIL变量:
-
PATH变量:
-
HOSTNAME变量:
-
HISTSIZE变量:
-
umask:
-
调用/etc/profile.d/*.sh文件
~/.bash_profile的作用
-
用了~/.bashrc文件。
-
在PATH变量后面加入了“:$HOME/bin”这个目录
5.6.3 其他配置文件和登录信息
注销时生效的环境变量配置文件
- ~/.bash_logout
其他配置文件
- ~/bash_history
Shell登录信息
- 本地终端欢迎信息: /etc/issue
5.7、正则表达式
5.7.1 正则表达式与通配符
-
正则表达式用来在文件中匹配符合条件的字符串,
正则是包含匹配
。grep、awk、sed等命令可以支持正则表达式。 -
通配符用来匹配符合条件的文件名,
通配符是完全匹配
。ls、find、cp这些命令不支持正则表达式,所以只能使用shell自己的通配符来进行匹配了。
基础正则表达式
示例1:"*" 前一个字符匹配0次或多次
● grep "a*" test_rule.txt
#匹配所有内容,包括空白行
● grep "aa*" test_rule.txt
#匹配至少包含有一个a的行
● grep "aaa*" test_rule.txt
#匹配最少包含两个连续a的字符串
● grep "aaaaa*" test_rule.txt
#则会匹配最少包含四个个连续a的字符串
示例2:"." 匹配除了换行符外任意一个字符
● grep "s..d" test_rule.txt
#“s..d”会匹配在s和d这两个字母之间一定有两个字符的单词
● grep "s.*d" test_rule.txt
#匹配在s和d字母之间有任意字符
● grep ".*" test_rule.txt
#匹配所有内容,0或多个任意字符
示例3: "^" 匹配行首,"$" 匹配行尾
● grep "^M" test_rule.txt
#匹配以大写“M”开头的行
● grep "n$" test_rule.txt
#匹配以小写“n”结尾的行
● grep -n "^$" test_rule.txt
#会匹配空白行
示例4:"[]" 匹配中括号中指定的任意一个字符,只匹配一个字符
● grep "s[ao]id" test_rule.txt
#匹配s和i字母中,要不是a、要不是o
● grep "[0-9]" test_rule.txt
#匹配任意一个数字
● grep "^[a-z]" test_rule.txt
#匹配用小写字母开头的行
示例5:"[^]" 匹配除中括号的字符以外的任意一个字符
● grep "^[â-z]" test_rule.txt
#匹配不用小写字母开头的行
● grep "^[â-zA-Z]" test_rule.txt
#匹配不用字母开头的行 “\” 转义符
● grep "\.$" test_rule.txt
#匹配使用“.”结尾的行
示例6:"\{n\}" 表示其前面的字符恰好出现n次
● grep "a\{3\}" test_rule.txt
#匹配a字母连续出现三次的字符串
● grep "[0-9]\{3\}" test_rule.txt
#匹配包含连续的三个数字的字符串
示例7:"\{n,\}" 表示其前面的字符出现不小于n次
● grep "^[0-9]\{3,\}[a-z]" test_rule.txt
#匹配最少用连续三个数字开头的行
示例8:"\{n,m\}" 匹配其前面的字符至少出现n次,最多出现m次
● grep "sa\{1,3\}i" test_rule.txt
#匹配在字母s和字母i之间有最少一个a,最多三个a
5.8 字符串截取命令
5.8.1 cut 字段提取命令
[root@localhost ~]# cut [选项] 文件名
选项:
-f 列号: 提取第几列
-d 分隔符: 按照指定分隔符分割列
1.创建演示文件student.txt
[root@localhost ~]# vi student.txt
ID Name gender Mark
1 Liming M 86
2 Sc M 90
3 Gao M 83
示例
[root@localhost ~]# cut -f 2 student.txt
#提取第二列
[root@localhost ~]# cut -f 2,3 student.txt
#提取第二第三列
[root@localhost ~]# cut -d ":" -f 1,3 /etc/passwd
#以:为分隔符提取第一第三列
2.cut命令的局限
[root@localhost ~]# df -h | cut -d " " -f 1,3
#有空格时提取会出问题,不能识别多个空格情况
5.8.2 printf 命令
[root@localhost ~]# printf ’输出类型输出格式’ 输出内容
输出类型:
%ns : 输出字符串。n是数字指代输出几个字符
%ni : 输出整数。n是数字指代输出几个数字
%m.nf : 输出浮点数。m和n是数字,指代输出的整数位数和小数位数。如%8.2f代表:2位是小数,8位是整数。
其中输出格式选项有:
输出格式:
控制字符 | 作用 |
---|---|
\a | 输出警告声音 |
\b | 输出退格键,也就是Backspace键 |
\f | 清除屏幕 |
\n | 换行 |
\r | 回车,也就是Enter键 |
\t | 水平输出退格键,也就是Tab键 |
\v | 垂直输出退格键,也就是Tab键 |
5.8.3 awk 命令
[root@localhost ~]# awk ‘条件1{动作1} 条件2{动作2}…’ 文件名
条件(Pattern):
一般使用关系表达式作为条件
x > 10 判断变量 x是否大于10
x>=10 大于等于
x<=10 小于等于
动作(Action):
格式化输出
流程控制语句
示例
[root@zhangRabbitMQ zhang]# vi /tmp/student.txt
id name java linux mysql
1 bilei 88 88 88
2 zhang 60 60 60
[root@zhangRabbitMQ zhang]# awk '{printf $2 "\t" $5 "\n"}' /tmp/student.txt
name mysql
bilei 88
zhang 60
BEGIN
#awk 'BEGIN{printf "This is a transcript \n" } {printf $2 "\t" $6 "\n"}' student.tx
END
# awk 'END{printf "The End \n" }
{printf $2 "\t" $6 "\n"}' student.txt
FS内置变量
#cat /etc/passwd | grep "/bin/bash" | awk 'BEGIN {FS=":"} {printf $1 "\t" $3 "\n"}'
关系运算符
#cat student.txt | grep -v Name | awk '$6 >= 87 {printf $2 "\n" }'
5.8.4 sed 命令
sed 是一种几乎包括在所有 UNIX 平台(包括 Linux)的轻量级流编辑器。sed主要是用来将数据进行选取、替换、删除、新增的命令。
[root@localhost ~]# sed [选项] ‘[动作]’ 文件名
选项:
-n: 一般sed命令会把所有数据都输出到屏幕 , 如果加入此选择,则只会把经过 sed命令处 理的行输出到屏幕。
-e: 允许对输入数据应用多条sed命令编辑
-i: 用sed的修改结果直接修改读取数据的文件, 而不是由屏幕输出
动作:
a \: 追加,在当前行后添加一行或多行。添加多行时,除最后 一行 外,每行末尾需要用“\”代 表数据未完结。
c \: 行替换,用c后面的字符串替换原数据行,替换多行时,除最 后一行外,每行末尾需“\”代 表数据未完结。
i \: 插入,在当期行前插入一行或多行。插入多行时,除最后 一行 外,每行末尾需要“\”代
表数据未完结。
d: 删除,删除指定的行。
p: 打印,输出指定的行。
s: 字串替换,用一个字符串替换另外一个字符串。格式为“行范 围s/旧字串/新字串/g”(和vim
中的替换格式类似)。
示例
[root@zhangRabbitMQ zhang]# vi /tmp/student.txt
id name java linux mysql
1 bilei 88 88 88
2 zhang 60 60 60
#查看文件的第二行
[root@zhangRabbitMQ tmp]# sed '2p' student.txt
id name java linux mysql
1 bilei 88 88 88
1 bilei 88 88 88
2 zhang 60 60 60
#只显示第二行
[root@zhangRabbitMQ tmp]# sed -n '2p' student.txt
1 bilei 88 88 88
#删除第二行到第四行的数据,但不修改文件本身
[root@zhangRabbitMQ tmp]# sed '2,3d' student.txt
id name java linux mysql
5.9 字符处理命令
5.9.1 排序命令 sort
[root@localhost ~]# sort [选项] 文件名
选项:
-f: 忽略大小写
-n: 以数值型进行排序,默认使用字符串型排序
-r: 反向排序
-t: 指定分隔符,默认是分隔符是制表符
-k n[,m]: 按照指定的字段范围排序。从第n字段开始,m字段结束(默认到行尾)
示例
[root@localhost ~]# sort /etc/passwd
#排序用户信息文件
[root@localhost ~]# sort -r /etc/passwd
#反向排序
[root@localhost ~]# sort -t ":" -k 3,3 /etc/passwd
#指定分隔符是“:”,用第三字段开头,第三字段结尾排序,就是只用第三字段排序
[root@localhost ~]# sort -n -t ":" -k 3,3 /etc/passwd
#指定分隔符是“:”,用第三字段开头,第三字段结尾排序,以数值型进行排序
5.9.2 wc 统计命令
[root@localhost ~]# wc [选项] 文件名
选项:
-l: 只统计行数
-w: 只统计单词数
-m: 只统计字符数