shell脚本中的文本处理

文本处理三剑客—“grep”

grep是Linux中最常用的“文本处理工具”之一,grep与sed、awk合称为Linux中的三剑客。
grep的全称为:Global search Regular Expression and Print out the line
全称中的“Global search”为全局搜索
全称中的“Regular Expression”表示正则表达式
即,grep是一个可以利用“正则表达式”进行“全局搜索”的工具,grep会在文本中按照指定的正则进行全局搜索,并将搜索出的行打印出来
当然,不通过正则表达式的方式也可以使用grep,但是当grep和正则表达式结合在一起时,功能威力更加强大

正则表达式,分为基本正则表达式和扩展正则表达式。
而grep默认支持基本正则表达式,不识别扩展正则表达式。如果想要令grep识别扩展正则表达式需要加上参数-E

关于正则表达式,可以参考以下博客:
https://www.cnblogs.com/Dlg-Blog/p/8733908.html

grep常用参数及搜索匹配模式

-i 忽略大小写
(如: grep -i root passwd 可以识别在passwd中的root,ROOT,Root,或root中任意字母大写的情况) 
-n 显示匹配到的字符行在原文件中的行数
-2 显示匹配到的行的上下两行
-n2 显示搜到的结果的上下两行,并标示出行号
-A1 显示搜到的结果的下面一行
-B1 显示搜到的结果的上面一行
-E 用于识别扩展正则表达式,如:* (grep默认只支持基本正则表达式)
egrep == grep -E 这两条命令是等价的
-v 除了符合条件的被显示(不显示符合条件的,只显示不符合条件的)
grep -E "^root" passwd 显示在passwd文件中以root开头的行
grep -E "root$" passwd 显示在passwd文件中以root结尾的行
grep -Ei "^root|root$" passwd -v | grep root 显示在passwd文件中,root字符串在中间的行
(因为如果不二次过滤,不仅有root在中间的情况,还有不包含root的情况)

正规的 grep 不支持扩展的正则表达式, 竖线'|'是用于表示”或”的扩展正则表达式元字符 , 正规的 grep 无法识别。加上反斜杠 , 这个字符就被翻译成扩展正则表达式。

下图为例:
图一,二中,grep会将包含搜索关键词的行显示出来,并将关键词以红色字体显示
同时,grep默认是不支持*这个通配符的,必须加上-E参数才能识别,或者以\*将*号转义,此时这只是一个符号,而不再指代任意个数的任意符号。
使用-i参数,忽略匹配关键词中的大小写差异

图三中,grep -Ei "^root|root$" passwd -v | grep root命令将显示root关键词在行中间部分的情况。我本来以为不需要-i参数就可以,但是实际操作中,不加该参数无法实现目标效果

图四中,由于一个匹配行是第一行,因此无法显示出其上面的行
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

grep中字符匹配

x..y #x和y之间有两个字符   .表示一个字符
x*y #表示x出现0-任意次(*之前的字符出现0-任意次)
x?y #出现0-1次
x+ #字符x出现1-任意次
x{n} #字符x出现n次,并解除贪婪模式,前后都不显示其他的
grep -E “\<x{1}y” westos #x至少出现一次,解除贪婪模式
grep -E “\xy{1}” westos #y至少出现一次,解除贪婪模式
grep -E “\(xy){1}” westos #xy至少出现一次,解除贪婪模式
x{m,n} #字符x至少出现m次,最多出现n次
x{m,} #字符x至少出现m次
x{,n} #字符x至多出现n次

解释:
grep x*y
相当于匹配y xy xxy xxxy ...  等等情况的合集

grep x?y
相当于匹配y xy两种情况的合集

grep x+y
相当于匹配xy xxy xxxy xxxxy等等情况的合集

注意:
grep使用的是贪婪模式
即,只要包含了搜索的字符,即便有多余的字符,也都会显示;而不是显示只含有关键词的行

\<关键字 左边除了关键字,不能有多余的字符
关键字\> 右边除了关键字,不能有多余的字符
\<关键字\> 除了关键字,不能有多余的字符

下图为例:
图一中,grep x*y file搜索出的xyyyoo这一结果,并不是匹配到xyyy这个关键词,而是同时匹配到了xy y y这三种情况。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

文本处理三剑客—“sed”

sed,行编辑器,英文全称为:stream editor
用来操作纯 ASCII 码的文本,在处理时会把当前处理的行存储在临时缓冲区中 , 称为“模式空间” (pattern space) 可以指定仅仅处理哪些行
sed对于符合模式条件的行进行处理,不符合条件的不予处理
处理完成之后把缓冲区的内容送往屏幕输出显示,接着处理下一行 , 这样不断重复 , 直到文件末尾

调用sed命令有两种形式:

sed [options] ‘command’ file(s)
sed [options] -f scriptfile file(s)

-n 屏蔽模式空间里的数据(内存缓存空间中的数据)

p模式 显示,打印print
d模式 删除(不显示)
a模式 添加
i模式 插入
(a和i其实是一样的,只不过一个是在指定的行下面添加(a),一个是在指定的行上面添加(i))
c模式 修改
w模式 写入
(将sed命令操作的文本写入文件,根据操作实际修改文件本身,但是可能显示与文件的修改并不同)

sed处理文件文本时,会将该文件读入内存,模式空间
p,d,a等模式操作的是模式空间(内存中的文本),而不会更改原文件的内容

常用形式:

sed '/^UUID/p' fstab
显示文件fstab中以UUID开头的行,且会显示模式空间中的文本
(模式空间文本即整个fstab文件文本内容;因此UUID开头的行会显示两遍,模式空间中一遍,命令要求显示一遍)

sed '/^UUID/p' -n fstab
仅显示文件fstab中以UUID开头的行,不显示(屏蔽)模式空间中的文本

sed '1,4p' -n fstab
显示文件fstab中1-4行

sed '1p;4p' -n fstab
显示文件fstab中1行和第4行
(这其实就是两条命令了)

sed '/0$/p;/^7/p' -n fstab
显示文件fstab中以0结尾的行,和以7开头的行(行前不能有空格,否则会认为是以空格开头)

sed '/^#/d' fstab
将文件fstab中以#开头的行删除显示(d模式)

sed '/^#/!d' fstab
将文件fstab中除了以#开头的行删除显示(d模式)
(d模式不能加-n参数,否则没有显示内容)

sed '/^#/ahello\nwestos' fstab
在文件fstab中以#开头的行下面添加hello westos两行字符串显示(中间的\n转义字符表示换行符号)

sed '/^#/ihello\nwestos' fstab
在文件fstab中以#开头的行上面插入hello westos两行字符串显示

sed '/^#/chello westos' fstab
将文件fstab中以#开头的行更改为hello westos显示(c模式)

sed '/^#/w /mnt/westos' fstab
将文件fstab中以#开头的行写入文件/mnt/westos(应该使用相对路径也可以被识别)

sed -n '/^#/w /mnt/westos' fstab
将文件fstab中以#开头的行写入文件/mnt/westos
(但并不显示fstab文件内文本)

sed '/^#/=' fstab
将文件fstab中以#开头的行,每一行的前一行显示行号
(在文件整体中的行号,而不是所显示内容中的行序号)

sed '/^#/=' fstab > file1
将前一条命令的显示结果写入文件 ./file1

sed '/^#/=' -i file1
使用sed命令读取并操作file1文件,并将操作结果写入原文件
(-i参数向文件中写入,使用此参数更改原文件)

但是,注意:
不能写作如下形式
sed '/^#/=' file > file
无法用sed命令输出重定向将所操作的文件本身更新

sed '/^[[:digit:]]/d' fstab -i file1 (或者用[0-9]匹配数字)
将之前命令写入文件中的数字开头的行都删除
(-i参数向文件中写入,但是这个应该不是覆盖原文件写入,而是将在原文件基础上要做的操作写入)

sed '6r fstab' westos 
将fstab文件插入westos的第6行下面显示(将两个文件合并显示)

sed '6r fstab' -i westos 
将fstab文件插入westos的第6行下面显示,并写入westos

下图为例:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
注意:
vim是交互模式的,但无法在脚本中调用vim更改配置文件内容
此时就可以使用sed命令在脚本中更改配置文件

sed的其他用法:

sed -e '/^UUID/p' -e '/UUID/=' fstab   ==   sed '/^UUID/p;/UUID/=' fstab
-e参数的作用与分号;的作用相同,是令这两条命令分别执行的

sed -f rulefile fstab
将使用统一参数的多条sed命令的策略写入rulefile文件中
读取rulefile文件,使用该文件策略对fstab进行操作
(rulefile文件中写的就是sed命令中' '内的内容)

sed 's/#//g' file
将文件file中的所有行,所有列的#都替换为空
(相当于是vim file后,执行:s/#//g  详见我之前的vim操作的博客)

sed 's@#@@g' file
将文件file中的所有行,所有列的#都替换为空
即与上一条命令的功能完全相同,只是用@代替了/

sed '/2/,/4/s/#//g' file
将文件file中从字符串“2”所在行到字符串“4”所在行,所有列的#都替换为空

sed 'G' fstab
在fstab文件文本的每一行下加一空行

sed '$G' fstab
只在fstab文件文本的最后一行下加一空行

sed '$!G' fstab
在fstab文件文本的每一行下加一空行,但最后一行下面不加空行

sed '=' fstab
将fstab文件内容读取到内存模式空间中,将模式空间中的文本每一行前一行加上行号并显示

sed '=' fstab | sed 'N;s/\n//g'
清空fstab模式空间文本中的空行(将空行替换为无)
sed对于模式空间的内容是逐行读取的,因此想要去掉回车空行,将两行读取合并为一行,需要sed程序提前加载下一行的内容(因此下面的命令不行:sed '=' fstab | sed 's/\n//g')
N提前加载以下行的内容

sed -n ‘$p’ file
将file文件的最后一行($)打印显示出来(p)

下图为例:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

文本处理三剑客—“awk”

awk是一个报告生成器,它拥有强大的文本格式化的能力
linux 上面默认使用 gawk

awk 处理机制 :awk 会逐行处理文本 , 支持在处理第一行之前做一些准备工作 , 以及在处理完最后一行做一些总结性质的工作 , 在命令格式上分别体现如下:

BEGIN{ }: 读入第一行文本之前执行 , 一般用来初始化操作
{ }: 逐行处理 , 逐行读入文本执行相应的处理 , 是最常见的编辑指令块
END{ }: 处理完最后一行文本之后执行 , 一般用来输出处理结果

awk常见用法:

awk '{print FILENAME}' passwd
(FILENAME不加‘’引号,会被识别为一个可用的变量;而加上引号会被识别为文本)
打印输出文件名,由于awk会逐行操作,对passwd文件的每一行操作
每操作一行,就会执行一次print操作,输出一次文件名;
因此,该命令最后输出多少行文件名,是要看文件本身有多少行

awk中默认变量NR,NF代表第几行,有多少列
(多少列的判定是根据分隔符决定的)
默认分隔符为空格
awk '{print NR}' passwd 
打印输出passwd文件的行的序号

awk -F:'{print NF}' passwd  
-F参数,指定分割符 
以:作为分割符,统计passwd的每一行有多少列

awk -F : 'BEGIN{print “NAME”}{print "NR"}END{print "BYE"}' passwd 
awk开始执行的时候显示“NAME”,再打印行的序号,执行结束后再打印“BYE“

awk -F : 'BEGIN{print “NAME”}{print $1}END{print "BYE"}' passwd 
awk开始执行的时候显示“NAME”,再打印该行的变量$1的值,执行结束后再打印“BYE“

awk -F : 'BEGIN{print “NAME”}{print $1,$2}END{print "end"}' passwd  
(或awk -F : 'BEGIN{print “NAME”}{print $1 $2}END{print "end"}' passwd)  

awk -F : 'BEGIN{print “NAME”}{print $0}END{print "end"}' passwd 
print $0 打印所有列($0所包含的所有的变量的值)

awk -F :'BEGIN{print “NAME”}{print $1="";print $0}END{print "end"}' passwd##打印第2行到第7行,$1=""相当于对第一列进行删除,但并不会改变原文件
注意的是,这样的命令不显示分割符,如果需要添加分隔符,需要添加

awk -F 'BEGIN{print “NAME”}{print $1="";print $0}END{print "end"}' passwd | sed 's/ /:/g'
该命令就是在上一命令的基础上加上了分割符:

awk '/bash$/{print}' passwd  
打印以bash结尾的行

awk '!/bash$/{print}' passwd  
打印除了以bash结尾的行以外的行

awk '/^root/ && /bash$/{print}' passwd  
打印以root开头,同时以bash结尾的行

awk '/^root/ || /bash$/{print}' passwd  
打印以root开头,或者以bash结尾的行

awk '!/bash$/&&!/nologin/{print}' passwd  
打印不以bash结尾且不含有nologin的行

awk '/\<bash$/{print}' passwd  
打印以bash结尾的行,并且解除关键词左侧的贪婪模式

awk 'BEGIN{n=0}/bash$/{n++}END{print n}' passwd 
用变量n计算一共有多少行以bash结尾
(以bash结尾的行一共有多少行,去掉/bash$/可以用来计算该文件的总行数)

awk '/^[a-c]/{print}' passwd   
打印以a,b,c开头的行
(筛选出以a,b或c开头的行,并将其打印出来)

awk -F : '$6~/bin/{print}' passwd   
打印第六列中为bin的行,默认贪婪模式(如:sbin也会被匹配到)
(匹配$6变量的值,可以与bin字符串相匹配的行,并打印出来)

awk -F : '$6~/bin/{print}' passwd 
打印第六列中bin的行

awk -F :'$6!~/\<bin\>/{print}' passwd 
打印第6列不包含,不匹配bin的行,退出贪婪模式

awk -F :'!/nologin$/{print $1}' /etc/passwd 
显示可以登录的用户的名称
(打印出不含nologin字符串的行的$1的值)

awk -F :'BEGIN{n=0}/bash$/&&$6!~/^\/home/{n++}END{print n}' passwd  
统计可登录并且加目录不在/home下的用户

下图为例:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值