您的位置:首页 > 运维架构 > Shell

《Linux命令、编辑器与Shell编程》读书笔记4.1-查找和筛选工具(grep,find,sed)

2015-11-06 22:11 555 查看
一、查找文件名工具find

find [path] [expression]

path:要查找的路径,如果不指定,默认为当前文件夹。

expression:有选项、测试和动作三类参数组成

1. 选项:

(1)depth,先查找当前目录,然后查找其下子目录

(2)maxdepth n,向下搜索到第n层目录

(3)mindepth n,至少向下搜索n层目录

(4)mount,不搜索本地文件中挂在的远程文件,比如:

find / -name "file" -mount -print

(5)follow,如果搜到链接文件、就连同其指向的文件一并检查

2. 常用测试参数:

(1)name:按文件名查找;比如在当前目录搜索后缀名为conf的文件:

find -name "*.conf" -print

* 在bash和csh里试了下,不加-print、显示结果是一样的。

(2)perm:按文件权限查找,比如查找权限为664的文件:

find / -perm 664 -print

(3)type:查找某一类型的文件;比如:

查找/dev目录下的字符设备:

find /dev -type c

查找/dev目录下的块设备:

find /dev -type b 

查找/etc/目录中除链接文件之外的文件:

find /etc ! -type l

(4)mtime+n(或-n):按修改时间查找,+n表示修改时间距今n天前,-n表示距今n天内

(5)atime+n(或-n):按文件的访问时间查找

查找修改时间在7天以内的文件:

find / -mtime -7

查找修改时间在1天前的文件:

find ~ -mtime +1

查找访问时间在10天以内的文件:

find / -atime -10

(6)size n[c]:查找文件长度为n块的文件,c表示文件大小为n字节的文件,比如:

查找文件长度大于10MB的文件

find -size +10000000c

查找文件长度小于30块(30x512B)的文件:

find -size -30 

(7)User:按文件属主查找

查找属主为users的文件:

find / -user users 

(8)group:按文件属组查找

查找属组为admin的文件:

find / -group admin

(9)nouser:查找没有有效属主的文件(文件属主在/etc/passwd文件中不存在)

查找没有有效属主的文件

find / -nouser

(10)nogroup:查找没有有效属组的文件(文件属组在/etc/group文件中不存在)

查找没有有效属组的文件:

find / -nogroup

3. 常用动作参数:

(1)prune:不在指定目录中查找,比如:

#使用path、prune和name参数指定在除了/etc以外的整个目录中查找以.conf结尾的配置文件,使用参数o将两个不同的参数连接起来

find / -path "/etc" -prune -o -name "*.conf" -print

(2)print:将查找到的文件输出到标准输出

(3)exec:对查找到的文件执行exec动作后附带的shell命令

(4)ok:对查找到的文件执行ok动作后附带的shell命令, 并在每次执行前提示用户是否执行

格式为:

-exec [shell命令] {} \;

-ok [shell命令] {} \;

比如:

①查找目录backup_sys下以message开头的文件,然后将查找结果交给ls -l命令处理

find ./backup_sys -name "message*" -mtime +7 -exec ls -l  {} \;

②查找并删除两周以前的备份文件:
find ./backup_sys -name "message*" -mtime +14 -exec rm {} \;

③查找并删除两周以前的备份文件,并提示是否删除:

find ./backup_sys -name "message*" -mtime +14 -ok rm {} \;

* 一般来说,find命令至少要同时包含一个测试参数和动作参数,才能正常执行,如果没带动作参数,则默认为-print。
4. 使用xargs命令处理查找到的文件

exec和ok这两个动作参数有两个缺陷,如果find命令执行出来的结果列表过长、传递给后面的shell命令会出现参数列表溢出错误;二则是后面的shell命令一次对过多的参数执行、会严重影响性能。

xargs命令则可以避免这两种情况,比如上面的命令,还可以这么写:

find ./backup_sys -name "message*" -mtime +14 | xargs rm

二、文本查找工具grep

命令格式:grep [option] pattern [file]

*注意,pattern要用双引号引起来,否则查找结果可能出现偏差,原因不明。后面的文件名可以用*等通配符代替、也可以用具体的文件名代替;如果pattern中使用了正则表达式、则要用单引号引起来

假设系统存在如下文件student,注意文件上传后要用dos2unix转换一下,转换完成后使用sed '1,$l' student查看一下行尾是否还有\r存在,否则行尾的换行符会影响下面的实验结果:

1234 aa1
23 32 6512040

2234 bb2
23 34 6612341

3234 cc3
24 36 6712742

4234 aa2
25 38 6813144

5234 bb3
26 40 6913545

6234 cc4
27 42 7013946

7234 aa3
28 44 7114348

8234 bb4
29 46 7214749

9234 cc5
30 48 7315150

1567 aa4
31 50 7415552

2567 bb5
32 52 7515953

3567 cc6
33 54 7616354

4567 aa5
34 56 7716756

5567 bb6
35 58 7817157

6567 cc7
36 60 7917558

7567 aa6
37 62 8017960

8567 bb7
38 64 8118361

9567 cc8
39 66 8218762

1790 aa7
40 68 8319164

2790 bb8
41 70 8419565

3790 cc9
42 72 8519966

4790 aa8
43 74 8620368

5790 bb9
44 76 8720769

6790 cc1
45 78 8821170

 

option:

i:忽略大小写

n:将结果输出的同时,也输出该行的行号

s:在没有查找到匹配内容时、不显示错误信息

l:从多个文件中查找时、只输出匹配到内容的文件名称

h:从多个文件中查找时、只输出匹配到的内容,不显示文件名称

c:只输出匹配内容的总行数

v:反转查找,即输出匹配内容以外的行,比如,查找不包含字符aa和bb的行:

grep -vi "aa*" student | grep -vi "bb*"

1. 行首匹配,比如:

#查找行首字符串包含6的行:

grep '^6' student

#显示行首词第2、3个字符为79的行:

grep '^.79' student

2. 行尾匹配,比如:

#显示行尾字符串大于61的行

grep -v '[0-5][0-9]$' student | grep '[6-9][1-9]$'
3. 匹配某字符出现的次数,比如:

#查找字母e重复出现2次、且以p结尾的行

grep 'e\{2\}p$' student

#查找字母c至少出现2次的行:

grep 'c\{2,\}' student

#统计空行行数

grep -c '^$' student

4. 搜索包含cc或aa的行:

grep -E '*cc*|*aa*' student

搜索包含aa1和1234的行:

grep -i "aa1" student | grep "1234"

 

grep工具应用实例:

1. 精简配置文件:把某个文本中符合某一特征的行去掉、从而只输出需要的信息

比如,将某文件中#号/分号开头的行、空行之外的行输出到新的文件中:

cat student | grep -v '#' | grep -v '^;' | grep -v '^$' > student_jingjian

2. 从其他命令结果中筛选需要的信息:

#查找某个用户的进程

ps -ef | grep username

#查看某服务的状态

chkconfig --list | grep bluetooth

 

 三、流编辑器sed:按照预设的规则处理文本文件、然后输出编辑结果
ce75

 命令格式:

sed [option] command inputfile

sed [option] -f script-file inputfile

【常用Option】

n:不输出所有行,默认是输出所有行

e:允许在该选项后面加一条command,如果有多个command时,要用该选项逐一添加

【常用定位方式】

 可以精确给定sed一个行号或行号范围,也可以用正则表达式对待处理文本进行模式匹配。

(1)n:行号为n的行,比如,只输出第三行:

sed -n '3p' student

(2)m,n:行号范围,比如输出第三至第五行:

sed -n '3,5p' student

(3)m,n!:排除第m行到底n行

(4)/pattern1/pattern2/:匹配pattern1和pattern2的所有行,要用e选项将两个模式隔开,比如,输出包含cc和aa行:

sed -n -e '/aa/p' -e '/cc/p' student

(5)/pattern/,~n:从匹配pattern的行开始,向后n-1行之间的所有行

(6)/pattern/,+n:从匹配pattern的行开始,向后n行之间的所有行

(7)n,/pattern/:从第n行开始到匹配pattern之内的所有行,比如,输出从第二行开始到匹配含有cc的行之间的所有行:

sed -n '2,/cc/p' student

【常用编辑命令】



*最后一行第一个字母是Q

*关于s/pattern1/pattern2/flag的补充,常见的flag选项如下:

g:将所有匹配到的内容全部替换

n:仅对行内第n次匹配到的内容进行替换

p:如果进行了替换,就将模式空间的文本输出到标准输出

w file:如果进行了替换,就将模式空间的文本写入文件file中

对同一位置进行多次编辑、用{}将command包起来;对多个位置进行多次编辑用e选项添加多条编辑指令、或用|配合多个sed命令

【常用分支语句】

类似于C语言中的if和goto语句,如下:

:label    标记点。标记一个用于跳转的位置,不能多于8个字符

t label   测试指令,如果上一条替换指令成功执行,则转移到标记点label处继续执行,如果没有找到label,则直接跳到文件末尾

b label  无条件转移到标记点label处,如果没有找到label,则直接跳到文件末尾

【举例】

1. 显示:

(1)输出所有行首字符为4的行:

sed -n '/^4/p' student

(2)搜索包含字符cc的行号:

sed -n '/cc/=' student

(3)显示从匹配模式/aa/开始向下的1行内容:

sed -n '/aa/,~2p' student

2. 删除行:

(1)屏蔽所有以1开头的行、然后显示剩余得行;:

sed '/^1/d' student

(2)屏蔽包含aa和cc的行、然后显示剩余得行:

sed -e '/aa/d' -e '/cc/d' p student

(3)屏蔽前三行、显示剩余内容:

sed '1,3d' student

*在使用形如/pattern/,n的范围匹配模式时,应当注意模式匹配到的行和指定的行号之间的大小关系。如果出现大小倒置的情况,sed只能完成第一个匹配行的编辑任务。

3. 插入和修改文本

(1)在第一行下面新插一行,并将新内容输出到new.txt文件中:

sed '1a\This is a new line.' student > new.txt

(2)在行尾插入一行:

sed '$a\This is a new line.' student

(3)在第三行下面插入多行:

sed '3a\New first line.\nNew second line.' student

(4)直接调用脚本文件中的命令对目标文件进行编辑,比如

    (a)将下面三行插入到student文件中aa字符串所在行的前面:

cat insert.sed

/aa/i\

First line.\

Second line.\

Last line.

#调用脚本

sed -f insert.sed student

    (b)将调用文件中的行插入到目标文件的指定行后面:

cat ex

First line.

Second line.

#将ex文件中的行直接插入(使用参数r)到stuent的第三行下面

sed '3r ex' student

    (c)将以27开头的行替换成new line

cat instead.sed

/^27/c\

New Line.

#使用 f调用脚本文件执行替换,并将结果保存到file1中

sed -f instead.sed student > file1

*在定位的位置插入新行时,只能使用行号和匹配模式指定要编辑的行,不能指定一个范围。

4. 替换和其他编辑命令:

sed提供了两个用于替换文本的编辑命令s和y,他们的使用方法详细,但功能不同,格式如下:

s/pattern1/pattern2/flag

y/pattern1/pattern2/

s指令是将匹配到的pattern1用pattern2/替换;y指令则在此基础上要求匹配的模式与用来替换的文本字符数长度必须相等

假设存在以下文件student2:



(1)用tab制表符替换所有的#号,并将结果保存到文件student2.1里面

sed 's/\#\#/    /g' student2 | tee student2.1

(2)调用sed脚本,把其它符号替换成tab制表符,将行尾的\\去掉:

>cat replace.sed

s/\$\$/\t/g

s/\*\*/\t/g

s/\:\:/\t/g

s/\&\&/\t/g

s/\\\\//g

> sed -f replace.sed student2.1 | tee student2.2



最终,student2的内容被处理为如上格式

(3)将第三行第2个匹配到的2替换为9:

>sed '3s/2/9/2' student2.2

(4)寻找l开头的词,并将l替换为L:

>sed 's/\<l/\<L/g' student2.2

*上面这句还有问题,调试中

(5)查看隐藏的控制字符:

sed -n '1,$l' student2.2

(6)显示除了行号为1之外的行:

sed -n '1!'p'' student2.2

*这里要注意对p参数的引用,由于我的系统中定义过变量p,所有在这里要加单引号,否则会报错:

sed: -e expression #1, char 3: extra characters after command

如果你的系统中没有对p定义过变量,直接写p就好

更详细的可以参考:http://litaotao.blog.51cto.com/6224470/1288526?utm_source=tuicool&utm_medium=referral

(7)将含有A或B的行先输出,其他行后输出:

> sed -n '/^2/{/[AB]/p;/[AB]/!'H';$g;$p}' student2.2

*这里的‘H'和上面的'p'同理,解释:首先匹配以2开头的行,然后执行{}内的语句,{}里面用分号;将独立的语句行分开。当一行以2开头的记录被传到{}内后,先查看是否包含A或B,如果包含,则打印;不包含,则将这条记录暂时存放到保留空间(H参数),之后再检查这行是否是最后一行,如果是,则用保留空间中的文本替换模式空间中的文本($g参数),如果不是最后一行,则继续检查下一行的开头是否以2开头。循环往复

(8)执行多条命令,比如要将A、B分别替换为85,70

sed -e 's/A/85/g' -e 's/B/75/g' student2.2

(9)用变量c接收用户的输入,然后查找到对应的字符(串)替换成其他字符:(下面命令在bash Shell下才能执行,cshell的实现方法还在摸索)

read $c;sed "s/28321/$c/" student2.2 | tee student2.3

(10)将文本中的小写字母替换为大写:

sed 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/' student2.2

5. 处理文本中的控制字符

使用cat -v可以查看文本中隐藏的控制字符,如^M;这些在其他平台(如windows)下编辑生成的控制字符,会影响linux下shell命令的执行,因此需要去掉。

有现成的命令dos2unix可以使用,原理就是把文本中的^M等控制字符去掉,sed的实现方法如下:

sed 's/^M/g' shell.sh > new.sh

^M的输入方法,ctrl+V,松开V再按M,然后松开ctrl即可,注意^M一定要手动输入,不能复制粘贴

6.sed分支结构:不常用,了解即可



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  linux shell