linux shell3 --文件处理 grep sed

本文深入解析了Shell中的命令类型,包括内部命令、外部命令、别名、hash、函数和关键字的使用。详细介绍了文本处理工具grep、sed的工作原理及正则表达式的应用,通过实例展示了如何高效地使用这些工具进行文本搜索和编辑。

命令的类型:
1.内部命令
常驻于内存

[root@shell ~]# man .

这里的 点 “.” 也是一个命令,表示重新加载,等同于source 。
2.外部命令

内部命令是在内核中的,在安装操作系统和shell中的,开机时直接加载在内存中,外部命令是安装在硬盘上的,还要向硬盘和内存进行转换。
所以在进行编写shell时尽量使用内部命令,不要写臃肿命令。

3.别名

查看命令的别名列表

[root@shell ~]# alias

4.hash

查看命令的hash列表

[root@shell ~]# hash

Hash,只对外部命令生效,加载到内存中的hash表中,下次再使用时效率较高。

5.函数
先定义
后调用

6.关键字
if case while for …

对于文本文件的处理,主要用下面几个方法。
grep egrep fgrep:

sed:

正则表达式:

grep 全家桶和sed 后面跟的都是正则表达式。

grep的语法:

grep “正则表达式” 文件名

grep:用于查询文件中符合正则表达式的内容

正则表达式是一组有特殊含义的字符串,用这个来代表一类内容

正则表达式的字符分为元字符和普通字符。
普通字符:大小写字母和数字。
元字符:有特殊含义的字符。

测试文件:

[root@www shell]# cat test-file1.txt  //文件内容。
root
rooot
roooooot
rt
at
cat
caaaat
/s
/help
/fuck
dog/
pi/g
nam\e
AAAA
BBB
DDDDDD
AABB

1、^ 行首定位符

[root@www shell]# grep "^A" test-file1.txt   //在行首是A的行
AAAA
AABB

在这里其实"^A"就是一个正则表达式了。

2、$ 行尾定位符

[root@www shell]# grep "B$" test-file1.txt   //行尾是B的
BBB
AABB

3、. 单个任意字符

[root@www shell]# grep "r.t" test-file1.txt  //查询有r和t 之间有1个字符的项,没有结果
[root@www shell]# grep "r..t" test-file1.txt  //查询r和t之间有2个字符的项,有一个root。并输出来。
root

4、* 前面的字符可以是任意个(0~无穷大)

[root@www shell]# grep "r*t" test-file1.txt  //这个并不是查询r和t之间有无数个字符的,而是查询t前面有n个r的项,n取0-无穷大。
root   //这个是t前边有0个r
rooot  //t前边有0个r
roooooot
rt    //t前边有1个r
at    //t前边有0个r
cat
caaaat
[root@www shell]# grep "ro*t" test-file1.txt   //这个表示的是r和t之间有n个o,n取0-无穷大
root   //2个o
rooot   //3个o
roooooot   //6个o
rt   //0个o

5、[] 匹配指定字符组中的任意1个字符

	[A-Z]
	[a-z]
	[a-Z]		所有的字母
	[0-9]
	[a-Z0-9]	字母+数字
	[^a-Z0-9]	^取反,不是字母+数字==符号

栗子:

[root@www shell]# grep "^[a-c]" test-file1.txt   //以abc小写,开头的行。
at
cat
caaaat

6、 \ ( \ ) 、
标签,保存被匹配的字符
标签在一个表达式中,最多出现9个
从左向右,依次排序,第一个标签,\ 1 ;第二个 \ 2

[root@www shell]# grep "\(.\)\1\1" test-file1.txt  // 前边的\(.\)是查询任意字符,\1表示第一个位置(也就是与第一个任意字符相同)
#//所以这行命令的意思就是3个相同的字符连续出现的项。
rooot   //ooo 三个相连  符合所以搜出了
roooooot   //这个o正好是6个,所以符合2个3连,能被搜出。
caaaat //包含三连的
AAAA
BBB
DDDDDD

7、\ { \ }

\ { m \ } 前面的字符有m个
\ { m , \ } 前面的字符>=m个
\ { m , n \ } 前面的字符>=m且 <=n 个

[root@www shell]# grep "B\{3\}" test-file1.txt  //三个A相连的
BBB
[root@www shell]# grep "A\{3\}" test-file1.txt 
AAAA

8、\ <\ >
\ < 词首定位符
\ > 词尾定位符
词:单词 一串连续的字母、数字,每个词之间用符号分割,任意符号都可以。这个词可能不是一个“词” ,在这里,aaa可能就是一个词,lll可能是一个词。

[root@www shell]# grep "\<pi\>" test-file1.txt 
pi/g

pi后边有个字符,于是pi就被识别成一个词,能被搜索出来。

9、\ 转义。

这个字符后边跟的符号只是符号不代表别的意思。这个点就是单纯的点。

[root@www shell]# grep "\." test-file1.txt 
d.og

但是注意一点,在正则里单引号和双引号没有区别,在shell中有区别

””双引号不能屏蔽 \ 反斜杠 ` 反引号 $ 符号。遇到这几个不能识别成字符,直接识别成所含意思,哪怕转义也不行。单引号则可以强制识别成字符。
如下边的栗子:

[root@www shell]# grep "\$" test-file1.txt 
root
rooot
roooooot
rt
at
cat
caaaat
/s
/help
/fuck
dog/
pi/g
nam\e
AAAA
BBB
DDDDDD
AABB
too$
d.og
[root@www shell]# grep '\$' test-file1.txt 
too$

双引号里有 \ 转义了,但是依旧不能用,单引号里转义可以用。

拓展的正则元字符:

这个要跟在egrep后用。

	|+	前面的字符匹配>=1次(1~无穷大)
	?	前面的字符配置0次或1次
	()	== \(\)
	{m}		==	\{m\}
	{m,}	==	\{m,\}
	{m,n}	==	\{m,n\}
[root@www shell]# cat test-file2.txt 
abc
123
aaa
dfe
qwre
aaad
gggjuyhk
eswfsaaa
###
@$^#^
Q@W#E%R
adb dev ops
name is cat

上边是文件的内容。

栗子:
1、| 或。满足 a开头或者e开头的救会被搜索出来

[root@www shell]# egrep '^a|^e' test-file2.txt 
abc
aaa
aaad
eswfsaaa
adb dev ops

2、+ 表示+前的字母有1到正无穷个。
     ?表示?前的字符有0 或1 个。

//例子中表示d前边有1到正无穷个a 的项会被搜索出来。
[root@www shell]# egrep 'a+d' test-file2.txt 
aaad
adb dev ops
//这里表示d前边有1个或者有0个a 的会被搜索出来。aaad也满足条件。
[root@www shell]# egrep 'a?d' test-file2.txt 
dfe
aaad
adb dev ops

3、()

[root@www shell]# egrep '(a)\1\1' test-file2.txt 
aaa
aaad
eswfsaaa
这个等同于有 \  的那个。

4、{m}

[root@www shell]# egrep 'g{3}' test-file2.txt 
gggjuyhk
这些都等价于有\ 的那个。

fgrep

取消字符的特殊含义。

[root@www shell]# fgrep '^#' test-file2.txt 
@$^#^
//在这里,^这东西已经失去了意义,只是符号。

sed: sed也叫流编辑器,可以过滤和转换。
工作原理:
以行为单位处理文件,将一行流入模式空间进行操作,命令和选项将行操作完成后,输出到标准输出(控制台)。然后处理下一行。

sed默认会处理所有的行,哪怕不做操作,也会将全部的行都“流”一遍。

sed的语法格式:
sed [选项] ‘/定址/命令‘ 文件名

sed只有在语法格式出错是$?才会非0 ,剩下的情况都为0.
grep则是搜索不出来就为非0

sed的选项和命令:

选项:
	-n		关闭模式空间的输出
	-e		多点编辑
	-i		就地修改,直接编辑源文件
	-f		指定sed脚本的名字
	-r		支持拓正则
命令:
	d		删除匹配行
	p		打印匹配行
	q		退出模式空间
	s		替换,用一个字符替换另一个
	y		将字符转换为另一字符(不支持正则表达式)
	r		从文件中读
	w		另存为
	a		在匹配行下一行添加一行或多行
	i		在匹配行上一行添加一行或多行
	c		本行替换
	h H		将内容从模式空间弄到保留空间,h是重定向(覆盖),H是追加
	g G		讲内容从保留空间弄到模式空间,g是重定向(覆盖),G是追加

测试用文件如下:

[root@www shell]# cat test-file3.txt 
user1:x:2030:2030::/home/user1:/bin/bash
user2:x:2031:2031::/home/user2:/bin/bash
user3:x:2032:2032::/home/user3:/bin/bash
user4:x:2033:2033::/home/user4:/bin/bash
user5:x:2034:2034::/home/user5:/bin/bash
user6:x:2035:2035::/home/user6:/bin/bash
user7:x:2036:2036::/home/user7:/bin/bash
user8:x:2037:2037::/home/user8:/bin/bash
user9:x:2038:2038::/home/user9:/bin/bash
user10:x:2039:2039::/home/user10:/bin/bash
[root@www shell]# 

直接写命令,不加 - i 选项的话并不会直接修改源文件,只是在模式空间修改,然后输出。

d 删除含有匹配项的行

[root@www shell]# sed '1,3d' test-file3.txt 
user4:x:2033:2033::/home/user4:/bin/bash
user5:x:2034:2034::/home/user5:/bin/bash
user6:x:2035:2035::/home/user6:/bin/bash
user7:x:2036:2036::/home/user7:/bin/bash
user8:x:2037:2037::/home/user8:/bin/bash
user9:x:2038:2038::/home/user9:/bin/bash
user10:x:2039:2039::/home/user10:/bin/bash
//1,3 删除第一至第三行 只写1 表示删除第1行。

**e是多点编辑,**可以这样使用,删除1和3行。

[root@www shell]# sed -e '1d' -e '3d' test-file3.txt 
user2:x:2031:2031::/home/user2:/bin/bash
user4:x:2033:2033::/home/user4:/bin/bash
user5:x:2034:2034::/home/user5:/bin/bash
user6:x:2035:2035::/home/user6:/bin/bash
user7:x:2036:2036::/home/user7:/bin/bash
user8:x:2037:2037::/home/user8:/bin/bash
user9:x:2038:2038::/home/user9:/bin/bash
user10:x:2039:2039::/home/user10:/bin/bash

p 打印输出 ,在模式空间中操作打印一行,再将模式空间中有的哪一行输出,所以是1-3行是2行。

[root@www shell]# sed '1,3p' test-file3.txt 
user1:x:2030:2030::/home/user1:/bin/bash
user1:x:2030:2030::/home/user1:/bin/bash
user2:x:2031:2031::/home/user2:/bin/bash
user2:x:2031:2031::/home/user2:/bin/bash
user3:x:2032:2032::/home/user3:/bin/bash
user3:x:2032:2032::/home/user3:/bin/bash
user4:x:2033:2033::/home/user4:/bin/bash
user5:x:2034:2034::/home/user5:/bin/bash
user6:x:2035:2035::/home/user6:/bin/bash
user7:x:2036:2036::/home/user7:/bin/bash
user8:x:2037:2037::/home/user8:/bin/bash
user9:x:2038:2038::/home/user9:/bin/bash
user10:x:2039:2039::/home/user10:/bin/bash

这个一般和-n一起使用:

这样模式空间的那一堆就不输出了,只输出 p 操作的,那几行。

[root@www shell]# sed -n '1,3p' test-file3.txt 
user1:x:2030:2030::/home/user1:/bin/bash
user2:x:2031:2031::/home/user2:/bin/bash
user3:x:2032:2032::/home/user3:/bin/bash

q 退出模式空间。
正常来说sed一行进入模式空间,然后输出,是必经的,会读取和操作所有行。 但是q ,会让在sed到指定行退出,也就不读取下边的行了。

[root@www shell]# sed 'q' test-file3.txt   //这个怎么都会都去一遍,第一行。
user1:x:2030:2030::/home/user1:/bin/bash
[root@www shell]# sed '1q' test-file3.txt 
user1:x:2030:2030::/home/user1:/bin/bash
[root@www shell]# sed '2q' test-file3.txt 
user1:x:2030:2030::/home/user1:/bin/bash
user2:x:2031:2031::/home/user2:/bin/bash

s:替换。
s的语法如下:
sed ‘s/模式匹配/替换内容/旗标’ 文件名
模式匹配:可以是正则表达式,也可以是普通的字符,当然普通的字符也可以算作正则表达式,只不过范围比较小。
替换内容:字符串,将模式匹配替换成什么。这个不能使正则。
旗标:主要用的有下边几种
        n:1-512之间的正整数,表示第n次出现的匹配内容
        g:全局替换
        p:打印替换的行
        w:另存为
        i :不区分大小写

默认匹配第一个替换。

[root@www shell]# sed 's/u/U/' test-file3.txt 
User1:x:2030:2030::/home/user1:/bin/bash
User2:x:2031:2031::/home/user2:/bin/bash
User3:x:2032:2032::/home/user3:/bin/bash
User4:x:2033:2033::/home/user4:/bin/bash
....省略 不复制了。。。

n=2 , 替换每行第二个匹配的。

[root@www shell]# sed 's/u/U/2' test-file3.txt 
user1:x:2030:2030::/home/User1:/bin/bash
user2:x:2031:2031::/home/User2:/bin/bash
user3:x:2032:2032::/home/User3:/bin/bash
user4:x:2033:2033::/home/User4:/bin/bash

g,替换全局的

[root@www shell]# sed 's/u/U/g' test-file3.txt 
User1:x:2030:2030::/home/User1:/bin/bash
User2:x:2031:2031::/home/User2:/bin/bash
User3:x:2032:2032::/home/User3:/bin/bash

p 打印,嗯输出2行了

[root@www shell]# sed 's/u/U/p' test-file3.txt 
User1:x:2030:2030::/home/user1:/bin/bash
User1:x:2030:2030::/home/user1:/bin/bash
User2:x:2031:2031::/home/user2:/bin/bash
User2:x:2031:2031::/home/user2:/bin/bash

w另存为,可以制定一个文件,然后就不在控制台输出了。

[root@www shell]# sed -n 's/u/U/w wwww.txt' test-file3.txt 
[root@www shell]# cat wwww.txt 
User1:x:2030:2030::/home/user1:/bin/bash
User2:x:2031:2031::/home/user2:/bin/bash
User3:x:2032:2032::/home/user3:/bin/bash
User4:x:2033:2033::/home/user4:/bin/bash
User5:x:2034:2034::/home/user5:/bin/bash
User6:x:2035:2035::/home/user6:/bin/bash
User7:x:2036:2036::/home/user7:/bin/bash
User8:x:2037:2037::/home/user8:/bin/bash
User9:x:2038:2038::/home/user9:/bin/bash
User10:x:2039:2039::/home/user10:/bin/bash

i 不区分大小写的替换。

[root@www shell]# cat test-file1.txt 
root
rooot
roooooot
rt
at
cat
caaaat
/s
/help
/fuck
dog/
pi/g
nam\e
AAAA
BBB
DDDDDD
AABB
too$
d.og
[root@www shell]# sed -n 's/a/ii/igp' test-file1.txt 
iit
ciit
ciiiiiiiit
niim\e
iiiiiiii
iiiiBB
//这些东西都是可以一起使用的,全局的a和A,都换成ii,并且打印做了改变的行,不显示模式空间的输出。结果就在上边。

y 讲一个字符转换成另一个字符。

[root@www shell]# sed 'y/qwertyuioplkjhgfdsazxcvbnm/QWERTYUIOPLKJHGFDSAZXCVBNM/' test-file3.txt 
USER1:X:2030:2030::/HOME/USER1:/BIN/BASH
USER2:X:2031:2031::/HOME/USER2:/BIN/BASH
USER3:X:2032:2032::/HOME/USER3:/BIN/BASH
USER4:X:2033:2033::/HOME/USER4:/BIN/BASH
USER5:X:2034:2034::/HOME/USER5:/BIN/BASH
//把所有的小写字母换成大写。

a 在行下插入内容。
i 在行上插入内容。

[root@www shell]# sed 'a hhaha' test-file3.txt 
user1:x:2030:2030::/home/user1:/bin/bash
hhaha
user2:x:2031:2031::/home/user2:/bin/bash
hhaha
user3:x:2032:2032::/home/user3:/bin/bash
hhaha
......后边不复制了。。。。。
//不指定定址的话默认所有嘛。
[root@www shell]# sed '1a hhaha' test-file3.txt 
user1:x:2030:2030::/home/user1:/bin/bash
hhaha
user2:x:2031:2031::/home/user2:/bin/bash
user3:x:2032:2032::/home/user3:/bin/bash
user4:x:2033:2033::/home/user4:/bin/bash
//只在第一行后边加。
[root@www shell]# sed '1i hhaha' test-file3.txt 
hhaha
user1:x:2030:2030::/home/user1:/bin/bash
user2:x:2031:2031::/home/user2:/bin/bash
user3:x:2032:2032::/home/user3:/bin/bash
//行前加
[root@www shell]# sed '1i hhaha\njjjjjj' test-file3.txt 
hhaha
jjjjjj
user1:x:2030:2030::/home/user1:/bin/bash
user2:x:2031:2031::/home/user2:/bin/bash
user3:x:2032:2032::/home/user3:/bin/bash
//可以加多行的,\n是换行。

w 另存为,前边可以加行数

[root@www shell]# sed '3w test-www.txt' test-file3.txt 
user1:x:2030:2030::/home/user1:/bin/bash
user2:x:2031:2031::/home/user2:/bin/bash
user3:x:2032:2032::/home/user3:/bin/bash
..后边省略,这个是从模式空间输出的。-n 可以没有
[root@www shell]# cat test-www.txt 
user3:x:2032:2032::/home/user3:/bin/bash

r读取文件,行数与后边的文件行数相同。

[root@www shell]# sed -n 'r test-www.txt' test-file3.txt 
user3:x:2032:2032::/home/user3:/bin/bash
user3:x:2032:2032::/home/user3:/bin/bash
user3:x:2032:2032::/home/user3:/bin/bash
user3:x:2032:2032::/home/user3:/bin/bash
user3:x:2032:2032::/home/user3:/bin/bash
user3:x:2032:2032::/home/user3:/bin/bash
user3:x:2032:2032::/home/user3:/bin/bash
user3:x:2032:2032::/home/user3:/bin/bash
user3:x:2032:2032::/home/user3:/bin/bash
user3:x:2032:2032::/home/user3:/bin/bash

hH
gG
这个东西会启动一个叫保留空间的东西。
处理文本文件–模式空间(PATT)
可以用来存储文件内容(行)–保留空间(HOLD),保留空间,默认有一个空行

如果有hHgG命令就会将文件的行写到保留空间中,在输出模式空间的东西,如果只有h 将模式空间弄到保留空间,没有意义,有去有回才有用。

[root@www shell]# sed '1h;4g' test-file3.txt 
user1:x:2030:2030::/home/user1:/bin/bash
user2:x:2031:2031::/home/user2:/bin/bash
user3:x:2032:2032::/home/user3:/bin/bash
user1:x:2030:2030::/home/user1:/bin/bash
user5:x:2034:2034::/home/user5:/bin/bash
user6:x:2035:2035::/home/user6:/bin/bash
user7:x:2036:2036::/home/user7:/bin/bash
user8:x:2037:2037::/home/user8:/bin/bash
user9:x:2038:2038::/home/user9:/bin/bash
user10:x:2039:2039::/home/user10:/bin/bash

上边命令的执行过程:
sed读取第一行,将第一行复制到模式空间,因为是h所以会覆盖那个空行,现在保留空间有一行,也就是文件的第一行。在sed读取第二行是,没有操作。
在sed读取第4行时,有g命令,将保留空间的内容覆盖回模式空间,也就是将保留空间的内容,覆盖到模式空间的第4行,保留空间的内容时文件的第一行,最后的结果就是第一行覆盖第4行。
下边都没有命令,也就没有操作。
最终输出模式空间的内容,显示结果,第4行没有了取而代之的是第1行。

[root@www shell]# sed '1h;4G' test-file3.txt 
user1:x:2030:2030::/home/user1:/bin/bash
user2:x:2031:2031::/home/user2:/bin/bash
user3:x:2032:2032::/home/user3:/bin/bash
user4:x:2033:2033::/home/user4:/bin/bash
user1:x:2030:2030::/home/user1:/bin/bash
user5:x:2034:2034::/home/user5:/bin/bash
user6:x:2035:2035::/home/user6:/bin/bash
user7:x:2036:2036::/home/user7:/bin/bash
user8:x:2037:2037::/home/user8:/bin/bash
user9:x:2038:2038::/home/user9:/bin/bash
user10:x:2039:2039::/home/user10:/bin/bash

H、G是追加,不会删除原来行,执行过程同上,所以会出现两行。第4行没有被覆盖,后边还多了个第1行。

-i 加后缀名

[root@www 1111shell]# sed -i.hhh 's/cat/CAT/g' pet 
[root@www 1111shell]# cat pet
dog CAT bird fish
CAT dog fish bird
CAT CAT apple banana
hotdog fuck name sex
[root@www 1111shell]# cat pet.hhh 
dog cat bird fish
cat dog fish bird
cat cat apple banana
hotdog fuck name sex

-i 后边的后缀名随便写,就是备份用,会直接修改文件,但是也会备份源文件,源文件不做修改,后缀名就是新的后缀名。

和下边这个正好相反,下边的是修改新文件,源文件不动。

[root@www 1111shell]# sed 's/cat/CAT/g' pet.hhh > pet.txt
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值