Bash shell学习笔记(五)
课程目标
- 掌握常用的正则表达式元字符含义
- 掌握sed的删除行操作
- 掌握sed的打印行操作
- 掌握sed的增加行操作
- 掌握sed的修改替换操作
正则表达式
正则表达式介绍
正则表达式(Regular Expression、regex或regexp,缩写为RE),也译为正规表示法、常规表示法,是一种字符模式,用于在查找过程中匹配指定的字符。
几乎所有开发语言都支持正则表达式,后面学习的python语言里也有正则表达式.
linux里主要支持正则表达式的命令有grep, sed, awk
正则一
表达式 | 说明 | 示例 |
---|---|---|
[] | 括号里的字符任选其一 | [abc][0-9][a-z] |
[^] | 不匹配括号里的任意字符(括号里面的^号为"非",不是开头) | [^abc]表示不是a,不是b,不是c |
^ [] | 以括号里的任意单个字符开头(这里的^是开头的意思) | ^ [abc]:以a或b或c开头 |
^ [^] | 不以括号里的任意单个字符开头 | |
^ | 行的开头 | ^root |
$ | 行的结尾 | bash$ |
^$ | 空行 |
示例: 准备一个文件
# vim 1.txt
boot
boat
rat
rot
root
Root
brot.
查找有rat或rot字符的行
# grep r[oa]t 1.txt
rat
rot
brot.
查看非r字符开头,但2-4个字符为oot的行
# grep ^[^r]oot 1.txt
boot
Root
查找有非大写字母与一个o字符连接的行
# grep '[^A-Z]o' 1.txt
boot
boat
rot
root
Root # 这个也可以查出来,因为第2-3个字符符合要求
brot.
查找不以r和b开头的行
# grep ^[^rb] 1.txt
Root
查找以rot开头以rot结尾的行(也就是这一行只有rot三个字符)
# grep ^rot$ 1.txt
rot
查找.号结尾的字符,需要转义并引号引起来(比较特殊,因为下面就要讲到.号是特殊的元字符)
# grep "\."$ 1.txt
brot.
问题: 使用grep输出/etc/vsftpd/vsftpd.conf
配置文件里的配置(去掉注释与空行)
提示: grep -v取反
别忘了grep -E扩展模式可以实现或
如: grep -E "root|ftp" /etc/passwd# yum install vsftpd -y# grep -v ^# /etc/vsftpd/vsftpd.conf |grep -v ^$
# grep -v '^#|^$' /etc/vsftpd/vsftpd.conf
问题: 使用grep输出/etc/samba/smb.conf
配置文件里的配置(去掉注释与空行)
# yum install samba -y# grep -v -E '#|^;|^$' /etc/samba/smb.conf |grep [a-z]
注:
samba配置文件是个比较奇葩的配置文件,在不同版本格式都有所不同,所以不同版本会有不同的答案。请灵活对待
grep加上关键字颜色显示(centos7默认就有颜色)
在/etc/bashrc最后的空白处追加一句
# vim /etc/bashrc
alias grep='grep --color=auto'# source /etc/bashrc
正则二
表达式 | 功能 |
---|---|
[[:alnum:]] | 大小写字母与数字 |
[[:alpha:]] | 字母字符(包括大小写字母) |
[[:blank:]] | 空格与制表符 |
[[:digit:]]或[0-9] (常用) | 数字 |
[[:lower:]]或[a-z] (常用) | 小写字母 |
[[:upper:]]或[A-Z] ** (常用**) | 大写字母 |
[[:punct:]] | 标点符号 |
[[:space:]] | 包括换行符,回车等在内的所有空白 |
查找不以大写字母开头的行
# grep '^[^[:upper:]]' 1.txt # 这个取反的写法很特殊,^符在两个中括号中间(了解即可)
# grep '^[^A-Z]' 1.txt
# grep -v '^[A-Z]' 1.txt
查找有数字的行
# grep '[0-9]' 1.txt
# grep [[:digit:]] 1.txt
查找一个数字和一个字母连起来的行
# grep -E '[0-9][a-Z]|[a-Z][0-9]' grep.txt # grep -E是扩展模式,中间|符号代表"或者"
问题: 请问汉语描述grep [^a-z] 1.txt
是查找什么?
查找不全部是小写字母的行
示例: 输入一个字符,判断输入的是大写字母还是小写字母还是数字,还是其它
方法一:
#!/bin/bashread -n 1 -p "input a char:" char # -n 1代表输入1个字符后就自动回车了
echo # echo代表换行case "$char" in # 使用case语句对$char进程多分支判断[[:upper:]] ) # 正则表达式匹配大写字母,(注意:这里用[A-Z]匹配不了)echo "大写字母";;[[:lower:]] ) # 正则表达式匹配小写字母,(注意:这里用[a-z]匹配不了)echo "小写字母";;[[:digit:]] ) # 正则表达式匹配数字echo "数字";;* )echo "其它"
esac
方法二:
#!/bin/bashread -n 1 -p "input a char:" char # -n 1代表输入1个字符后就自动回车了
echo # echo代表换行# 使用if多分支进行判断
if [[ $char =~ [A-Z] ]];then # [[ ]]两个中括号里写判断条件,里面使用=~匹配正则表达式echo "大写字母"
elif [[ $char =~ [a-z] ]];thenecho "小写字母"
elif [[ $char =~ [0-9] ]];thenecho "数字"
elseecho "其它"
fi
练习: read -s输入一个密码, 判断此密码复杂度.(长度大于等于8位,并且有大小写字母和数字三类字符)
正则三
名词解释:
元字符: 指那些在正则表达式中具有特殊意义的专用字符, 如:点(.) 星(*) 问号(?)等
前导字符:即位于元字符前面的字符 abc * aooo .
注意: 元字符如果想表达字符本身需要转义,如.号就想匹配"."号本身则需要使用\.
字符 | 字符说明 | 示例 |
---|---|---|
* | 前导字符出现0次或者连续多次 | ab* abbbb |
. | 除了换行符以外,任意单个字符 | ab. ab8 abu |
.* | 任意长度的字符 | ab.* abdfdfdf |
{n} | 前导字符连续出现n次 (需要配合grep -E或egrep使用) | [0-9]{3} |
{n,} | 前导字符至少出现n次 (需要配合grep -E或egrep使用) | [a-z]{4,} |
{n,m} | 前导字符连续出现n到m次 (需要配合grep -E或egrep使用) | o{2,4} |
+ | 前导字符出现1次或者多次 (需要配合grep -E或egrep使用) | [0-9]+ |
? | 前导字符出现0次或者1次 (需要配合grep -E或egrep使用) | go? |
( ) | 组字符 |
示例文本:
# vim 2.txt
ggle
gogle
google
gooogle
gagle
gaagle
gaaagle
abcgef
abcdef
goagle
aagoog
wrqsg
问题:一起来看看下面能查出哪些字符,通过结果理解记忆
# grep g. 2.txt
# grep g* 2.txt # 结果比较怪
# grep g.g 2.txt
# grep g*g 2.txt
# grep go.g 2.txt
# grep go*g 2.txt
# grep go.*g 2.txt
# grep -E go{2}g 2.txt
# grep -E 'go{1,2}g' 2.txt # 需要引号引起来,单引双引都可以
# grep -E 'go{1,}g' 2.txt # 需要引号引起来,单引双引都可以
# grep -E go+g 2.txt
# grep -E go?g 2.txt
示例: 查出eth0网卡的IP,广播地址,子网掩码
# ifconfig eth0 | grep -E -o '([0-9]{1,3}\.){3}[0-9]{1,3}'
10.1.1.11
10.1.1.255
255.255.255.0
解析:
[0-9]{1,3}\. 代表3个数字接一个.号
([0-9]{1,3}\.){3} 前面用小括号做成一个组,后面{3}代表重重复3次
[0-9]{1,3} 最后一个数字后不需要.号
示例: 匹配邮箱地址
# echo "daniel@126.com" | grep -E '^[0-9a-zA-Z]+@[a-z0-9]+\.[a-z]+$'
解析:
^[0-9a-zA-Z]+@ 代表@符号前面有1个或多个字符开头(大小写字母或数字)
@[a-z0-9]+\.[a-z]+$ 代表@符号和.号(注意.号要转义)中间有1个或多个字符(小写字母或数字).号后面有1个或多个字符(小写字母)结尾
perl内置正则(拓展)
Perl内置正则(需要使用grep -P来匹配),这种匹配方式在python也有。但不建议都记住,上面所学的就完全够用了.
\d 匹配数字 [0-9]
\w 匹配字母数字下划线[a-zA-Z0-9_]
\s 匹配空格、制表符、换页符[\t\r\n]
sed
sed介绍
# man sed
sed - stream editor for filtering and trans-forming text
Windows下的编辑器:
linux下的编辑器:
- vi或vim
- gedit
- emacs等
- 首先sed把当前正在处理的行保存在一个临时缓存区中(也称为模式空间),然后处理临时缓冲区中的行,完成后把该行发送到屏幕上。
- sed把每一行都存在临时缓冲区中,对这个副本进行编辑,所以不会修改原文件。当然你也可以选择修改源文件,需要
sed -i 操作的文件
学习sed的关键是要搞清楚,它是一个流编辑器,编辑器常见的功能有:
- 删除行
- 打印行
- 增加行
- 替换(修改)
sed参数
-e 进行多项编辑,即对输入行应用多条sed命令时使用
-n 取消默认的输出
-r 使用扩展正则表达式
-i inplace,原地编辑(修改源文件)sed操作
d 删除行
p 打印行
a 后面加行
i 前面加行
s 替换修改
删除行操作
d(delete)代表删除
使用数字匹配行
指定删除第2行
# head -5 /etc/passwd |cat -n |sed 2d变量引用需要双引号
a=2
# head -5 /etc/passwd |cat -n |sed "$a"d
删除第2行到第3行,中间的逗号表示范围
# head -5 /etc/passwd |cat -n |sed 2,3d
删除第1行和第5行,中间为分号,表示单独的操作
错误,需要引号引起来
# head -5 /etc/passwd |cat -n |sed 1d;5d
正确
# head -5 /etc/passwd |cat -n |sed '1d;5d'
删除第1,2,4行, -e参数是把不同的多种操作可以衔接起来
head -5 /etc/passwd |cat -n |sed -e '2d;4d' -e '1d'
问题:下面操作代表什么
# head -n 5 /etc/passwd |cat -n |sed '1d;3d;5d'# head -n 5 /etc/passwd |cat -n |sed '1,3d;5d'
使用正则匹配行
如果不知道行号,但知道行里的某个单词或相关字符,我们可以使用正则表达式进行匹配
删除匹配oo的行
# head -n 5 /etc/passwd |cat -n |sed '/oo/d'
删除以root开头的行
# head -n 5 /etc/passwd |sed '/^root/d'
删除以bash结尾的行
# head -n 5 /etc/passwd |sed '/bash$/d'
其它任意正则表达式都可以匹配
练习:(注意: -i参数会直接操作源文件,所以请先不加-i测试,测试OK后再加-i参数)
sed -i
删除/etc/vsftpd/vsftpd.conf里所有的注释和空行
# sed -i '/^#/d;/^$/d' /etc/vsftpd/vsftpd.conf
sed -i
删除/etc/samba/smb.conf里所有的注释和空行
# sed -i '/#/d;/;/d;/^$/d;/^\t$/d' /etc/samba/smb.conf
打印行操作
打印行(删除的反义)
p(print)代表打印
使用数字匹配行
打印第1行
# head -5 /etc/passwd |cat -n | sed 1p1 root:x:0:0:root:/root:/bin/bash # 会在原来5行的基础上再打印第1行1 root:x:0:0:root:/root:/bin/bash2 bin:x:1:1:bin:/bin:/sbin/nologin3 daemon:x:2:2:daemon:/sbin:/sbin/nologin4 adm:x:3:4:adm:/var/adm:/sbin/nologin5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin# head -5 /etc/passwd |cat -n | sed -n 1p # 正确做法加一个-n参数1 root:x:0:0:root:/root:/bin/bash
打印第1行和第4行
# head -5 /etc/passwd |sed -ne '1p;4p'
打印1-4行
# head -5 /etc/passwd |sed -ne '1,4p'
使用正则匹配行
打印有root关键字的行
# head -5 /etc/passwd |sed -n '/root/p'
打印以root开头的行
# head -5 /etc/passwd |sed -n '/^root/p'
找出var/log/secure日志里成功登录的ssh信息
方法1:
# sed -n '/Accepted/p' /var/log/secure
方法2:
# grep Accepted /var/log/secure
方法3:(awk还没学,先了解一下)
# awk '$0~"Accepted" {print $0}' /var/log/secure
增加行操作
a(append)代表后面加行
i(insert)代表前面插入行
准备一个文件
# cat 1.txt
11111
22222
44444
55555
在第2行后加上33333这一行
# sed -i '2a33333' 1.txt
# cat 1.txt
11111
22222
33333
44444
55555
在第1行插入00000这一行
# sed -i '1i00000' 1.txt
# cat 1.txt
00000
11111
22222
33333
44444
55555
也可以用正则匹配行,这里表示在4开头的行的后一行加上ccccc这一行
# sed -i '/^4/accccc' 1.txt # cat 1.txt
00000
11111
22222
33333
44444
ccccc
55555
修改替换操作
sed的修改替换格式与vi里的修改替换格式一样
使用数字匹配行
替换每行里的第1个匹配字符
# head -5 /etc/passwd |sed 's/:/===/'
root===x:0:0:root:/root:/bin/bash
bin===x:1:1:bin:/bin:/sbin/nologin
daemon===x:2:2:daemon:/sbin:/sbin/nologin
adm===x:3:4:adm:/var/adm:/sbin/nologin
lp===x:4:7:lp:/var/spool/lpd:/sbin/nologin
全替换
# head -5 /etc/passwd |sed 's/:/===/g'
root===x===0===0===root===/root===/bin/bash
bin===x===1===1===bin===/bin===/sbin/nologin
daemon===x===2===2===daemon===/sbin===/sbin/nologin
adm===x===3===4===adm===/var/adm===/sbin/nologin
lp===x===4===7===lp===/var/spool/lpd===/sbin/nologin
替换2-4行
# head -5 /etc/passwd |sed '2,4s/:/===/g'
root:x:0:0:root:/root:/bin/bash
bin===x===1===1===bin===/bin===/sbin/nologin
daemon===x===2===2===daemon===/sbin===/sbin/nologin
adm===x===3===4===adm===/var/adm===/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
替换2行和4行
# head -5 /etc/passwd |sed '2s/:/===/g;4s/:/===/g'
root:x:0:0:root:/root:/bin/bash
bin===x===1===1===bin===/bin===/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm===x===3===4===adm===/var/adm===/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
替换第2行的第1个和第3个匹配字符
注意后面的数字是2,前面替换了1个,剩下的里面替换第2个也就是原来的第3个
# head -5 /etc/passwd |sed '2s/:/===/;2s/:/===/2'
root:x:0:0:root:/root:/bin/bash
bin===x:1===1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
使用正则匹配行
替换以daemon开头的那一行
# head -5 /etc/passwd |sed '/^daemon/s/:/===/g'
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon===x===2===2===daemon===/sbin===/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
&符号在sed替换里代表前面被替换的字符
理解下面两句的不同:
s/[0-9]/ &/
s/[0-9]/ [0-9]/
练习: 使用脚本实现修改主机名(假设改为a.b.com)
# hostname a.b.com
# sed -i '/HOSTNAME=/s/server.cluster.com/a.b.com/' /etc/sysconfig/network
# echo "10.1.1.11 a.b.com" >> /etc/hosts
练习: 修改/etc/selinx/config配置文件,将selinux关闭
# sed -i '/SELINUX=/s/enforcing/disabled/' /etc/selinux/config
sed分域操作(拓展)
将()之间的字符串(一般为正则表达式)定义为组,并且将匹配这个表达式的保存到一个区域(一个正则表达式最多可以保存9个),它们使用\1到\9来表示。然后进行替换操作
注意: sed分域操作的格式就是替换修改.
示例: 把hello,world.sed
变成world,sed.hello
(注意: 1个逗号1个点号)
方法1:
# echo "hello,world.sed" | sed 's/\(.*\),\(.*\)\.\(.*\)/\2,\3.\1/'
world,sed.hello
此方法\符太多了,建议使用-r扩展模式,就不用加\转义括号了方法2:
# echo "hello,world.sed" | sed -r 's/(.*),(.*)\.(.*)/\2,\3.\1/'
world,sed.hello方法3:
# echo "hello,world.sed" | sed -r 's/(.....)(.)(.....)(.)(...)/\3\2\5\4\1/'
world,sed.hello方法4:
# echo "hello,world.sed" | sed -r 's/(.{5})(.)(.{5})(.)(.{3})/\3\2\5\4\1/'
world,sed.hello
示例: 以/etc/passwd文件前5行为例,进行如下处理
删除每行的第一个字符
# head -5 /etc/passwd |cut -c2-
# head -5 /etc/passwd |sed -r 's/(.)(.*)/\2/'
# head -5 /etc/passwd |sed -r 's/.//1'
# head -5 /etc/passwd |sed -r 's/^.//'
删除每行的第九个字符
# head -5 /etc/passwd |cut -c1-8,10-
# head -5 /etc/passwd |sed -r 's/(.{8})(.)(.*)/\1\3/'
# head -5 /etc/passwd |sed -r 's/.//9'
删除倒数第5个字符
# head -5 /etc/passwd |rev |cut -c1-4,6- |rev
# head -5 /etc/passwd |sed -r 's/(.*)(.)(....)/\1\3/'
把每行的第5个字符和第8个字符互换,并删除第10个字符
# head -5 /etc/passwd | sed -r 's/(....)(.)(..)(.)(.)(.)(.*)/\1\4\3\2\5\7/'
课后练习
写一个简单初始化系统的脚本
1, 修改主机名(也就是说你获取IP为10.1.1.11,则主机名改成server11.cluster.com)
2, 配置可以使用的本地yum
3, 关闭防火墙与selinux
4, 安装配置vsftpd,不允许匿名用户登录,配置完后启动服务并设置为开机自动启动
5, 可在此基础上继续自由发挥扩展
Bash shell学习笔记(五)相关推荐
- Bash Shell学习笔记五
1.vim的模式下复制与粘贴 视图模式下: shift+d剪切 shift+p粘贴 shift+y复制 按下D可以整行删除 按delele键,可以逐一字符删除. 2.vim中的几个用法 1.搜索上一个 ...
- Bash Shell学习笔记四
1. 几个常用命令和基本知识. set $(commond) 将位置参数设置为后面的命令输出 shell命令中 在-- 后面的语句将会不再解释后面的 - cal 万年历 bc 计算器 ...
- bash linux .ee,Linux下Bash shell学习笔记.md
### 1.shell下没有变量类型和定义的概念. >1. 变量直接使用不用定义 >2. 所有值都视为字符串. >3. 在对变量取值都需要加$ >4. 行注释为 # + ### ...
- Bash Shell学习笔记二
1.||.&& 和&.|的区别 ||和&&的执行是从左到右,而&和|的执行是两边到中间的(未实际测试,只能确认它不是按顺序执行的) ||和&&a ...
- Bash Shell学习笔记三
1.eval的含义 eval实际上是对后面的算式或者表达式执行两次解释. 例如 a=sc bsc=feiye echo $a eval echo "$"b$a 最后一句实际上是执行 ...
- Bash Shell学习笔记一
1. 在Linux中执行脚本文件时 以 ./执行的 或者普通方式(输入文件名)执行时是启动子shell执行的,所以,一切环境变量设置在推出后失效 因此在脚本中设置$PATH将失效,如果一定要以脚本方式 ...
- Bash shell 学习笔记六
vim中统计单词的个数 统计hello单词的个数 :%s/hello/&/g 或 :%s+hello+&+g sed 的一个用法 echo 135.0.1.4|sed 's//./*( ...
- 【AngularJs学习笔记五】AngularJS从构建项目开始
为什么80%的码农都做不了架构师?>>> #0 系列目录# AngularJs学习笔记 [AngularJs学习笔记一]Bower解决js的依赖管理 [AngularJs学习笔 ...
- 华清远见fs4412开发板学习笔记(五)
fs4412开发板学习笔记(五) 作业1: 输入10个整数,按从小到大的顺序输出(选择排序) 每轮排序在未排序的集合中找到(最小/最大),将找到的数与未排序的 第一个数交换位置. 5 4 3 2 1 ...
最新文章
- lnmp ubuntu mysql装不上_ubuntu1.8安装lnmp失败
- 判断字符串1是否在字符串2中出现的方法
- TCP三次握手原理,你真的了解吗?
- 下载地图包,并基于python的pyshp库读取.shp数据来获取中国省界的经纬度数据
- Oracle Sql 胡乱记
- 【转】分布式事务的常见解决方案
- Python 装饰器理解
- 插入排序(java版)
- c语言vco_VCO仿真的方法
- 从java中安装webolgc_Javaweb| 文件下载
- 海量数据挖掘MMDS week5: 计算广告Computational Advertising
- tail -f 命令卡住
- 计算机输入输出设计原则,交互设计精髓4中的104条设计原则
- 手把手系列--华邦W25Q64JV Flash操作指南
- 视频黑屏检测,时长检测 blackdetect
- NFS 服务器启动失败
- HTML模拟唯品会登陆和注册页面
- BMI值(Body Mass Index,简称BMI),是指身高体重指数,是国际上常用的衡量人体肥胖程度和是否健康的重要标准,BMI的计算公式是:体重指数(BMI)=体重(kg)÷身高2(m)。
- YTU oj 3631 树的高度
- Python 字符串