Shell 常用工具 grep-find-xargs-sed-awk

grep

grep家族包括grep、egrep和fgrep,egrep是grep的扩展
默认情况下,‘grep’只搜索当前目录
格式:grep [options]
示例:$egrep “hello” t8.sh -v
主要参数

grep --help
[options]主要参数。
-c:只输出匹配行的计数
-i:不区分大小写
-h:查询多文件时不显示文件名
-l:查询多文件时只输出包含匹配字符的文件名
-n:显示匹配行 及 行号
-s:不显示不存在或无匹配文本的错误信息
-v:显示不包含匹配文本的所有行
-r 关键字 :搜索子目录
-d skip :忽略子目录
--color=auto:可以将找到的关键词部分加上颜色的显示

pattern正则表达式主要参数:

\:忽略正则表达式中特殊字符的原有含义
^:匹配正则表达式的开始行
$:匹配正则表达式的结束行
\<:从匹配正则表达式的行开始
\>:到匹配正则表达式的行结束
[]:单个字符,如[A]即A符合要求
[ - ]:范围,如[A-Z],即A、B、C到Z都符合要求
. :所有的单个字符
* :有字符,长度可以为0

grep 命令使用简单实例

$ grep 'test' d*
显示所有以d开头的文件中包含 test的行

$ grep 'test' aa bb cc
显示在aa,bb,cc文件中匹配test的行

$ grep '[a-z]\{5\}' aa
显示所有包含每个字符串至少有5个连续小写字符的字符串的行

下面还有一些有意思的命令行参数:

grep -i pattern files :不区分大小写地搜索。默认情况区分大小写,
grep -l pattern files :只列出匹配的文件名,
grep -L pattern files :列出不匹配的文件名,
grep -w pattern files :只匹配整个单词,而不是字符串的一部分(如匹配’magic’,而不是’magical’)grep -C number pattern files :匹配的上下文分别显示[number]行,
grep pattern1 | pattern2 files :显示匹配 pattern1 或 pattern2 的行,
例如:grep "abc\|xyz" testfile   表示过滤包含abc或xyz的行
grep pattern1 files | grep pattern2 :显示既匹配 pattern1 又匹配 pattern2 的行。
grep -n pattern files 即可显示行号信息
grep -c pattern files 即可查找总行数

这里还有些用于搜索的特殊符号:

\< 和 \> 分别标注单词的开始与结尾。
例如:
grep man * 会匹配 ‘Batman’、’manic’、’man’等
grep ‘\<man’ * 匹配’manic’和’man’,但不是’Batman’
grep ‘\<man\>’ 只匹配’man’,而不是’Batman’或’manic’等其他的字符串
‘^’:指匹配的字符串在行首
‘$’:指匹配的字符串在行尾

find

一、find 命令格式

  1. find命令的一般形式为
    find pathname -options [-print -exec -ok ...]

  2. find命令的参数

pathname:find命令所查找的目录路径。例如用 .来表示当前目录,用 /来表示系统根目录,递归查找
-print:find命令将匹配的文件输出到标准输出。
-exec:find命令对匹配的文件执行该参数所给出的shell命令。相应命令的形式为'command' { } ;,注意{ }和;之间的空格。
-ok:和-exec的作用相同,只不过以一种更为安全的模式来执行该参数所给出的shell命令,在执行每一个命令之前,都会给出提示,让用户来确定是否执行。
  1. find命令选项 (这些不用刻意去记,知道有这么回事,要用的时候再来找)
-name  按照文件名查找文件
-perm  按照文件权限来查找文件     find -perm 777
-user  按照文件属主来查找文件。
-nouser 指定无属主
-group 按照文件所属的组来查找文件。
-mtime -n +n  按照文件的更改时间来查找文件, - n表示文件更改时间距现在n天以内,+ n表示文件更改时间距现在n天以前。find命令还有-atime和-ctime 选项,但它们都和-m time选项。
-type  查找某一类型的文件,诸如:   -type f
    b - 块设备文件。
    d - 目录。
    c - 字符设备文件。
    p - 管道文件。
    l - 符号链接文件。
    f - 普通文件。
-size n:[c] 查找文件长度为n块的文件,带有c时表示文件长度以字节计。-depth:在查找文件时,首先查找当前目录中的文件,然后再在其子目录中查找。
-follow:如果find命令遇到符号链接文件,就跟踪至链接所指向的文件。

另外,下面三个的区别:(这些不用刻意去记,知道有这么回事,要用的时候再来找)

-amin n   查找系统中最后N分钟访问的文件
-atime n  查找系统中最后n*24小时访问的文件

-cmin n   查找系统中最后N分钟被改变文件状态的文件
-ctime n  查找系统中最后n*24小时被改变文件状态的文件

-mmin n   查找系统中最后N分钟被改变文件数据的文件
-mtime n  查找系统中最后n*24小时被改变文件数据的文件 
  1. 使用exec或ok来执行shell命令
    使用find时,只要把想要的操作写在一个文件里,就可以用exec来配合find查找,很方便 在有些操作系统中只允许-exec执行诸如 ls 或 ls -l 这样的命令。大多数用户使用这一选项是为了查找旧文件并删除它们。建议在真正执行 rm 命令删除文件之前,最好先用 ls 命令看一下,确认它们是所要删除的文件。
    -exec 和 -ok 等价

exec选项后面跟随着所要执行的命令或脚本,然后固定格式是一对儿{},一个空格和一个\,最后是一个分号。 为了使用exec选项,必须要同时使用print选项。

例1:为了用ls -l命令列出所匹配到的文件,可以把ls -l命令放在find命令的 -exec选项中

$ find . -type f -exec ls -l {} \;

例2:在/logs目录中查找更改时间再5日以前的文件并删除它们

$ find logs -type f -mtime +5 -exec rm {} \;

记住: 在shell中用任何方式删除文件之前,应当先查看相应的文件,一定要小心!当使用诸如mv 或 rm命令时,可以使用 -exec选项的安全模式,它将在对每个匹配到的文件进行操作之前提示你。

例3:在当前目录中查找所有文件名以 .LOG结尾、更改时间在5日以上的文件,并删除它们,只不过删除之前先给出提示

$ find . -name "*.conf" -mtime +5 -ok rm {} \;
< rm ... ./conf/httpd.conf > ? n

按y键删除文件,按n键不删除。
任何形式的命令都可以在 -exec选项中使用

例4:find命令首先匹配所有文件名为 “passwd”的文件,例如passwd,passwd.old,passwd.bak,然后执行grep命令看看在这些文件中是否存在一个 itcast 用户。

$ find /etc -name "passwd" -exec grep "itcast" {} \;
itcast:x:1000:1000::/home/itcast:/bin/bash

二、选项详解

  1. 使用name选项
    文件名选项是find命令最常用的选项,要么单独使用该选项,要么和其他选项一起使用
    可以使用某种文件名模式来匹配文件,记住要用引号将文件名模式引起来。

例1:不管当前路径是什么,如果想要在自己的根目录$HOME中查找文件名符合 *.txt的文化,使用~作为 'pathname’参数,波浪号~代表了你的 $HOME目录。

$ find ~ -name "*.txt" -print

例2:想要在当前目录及子目录中查找所有的 ’ *.txt’ 文件,可以用

$ find . -name "*.txt" -print

例3:想要在当前目录及子目录中查找文件名以一个大写字母开头的文件,可以用

$ find . -name "[A-Z]*" -print

例4:想要在/etc目录中查找文件名以host开头的文件,可以用

$ find /etc -name "host*" -print

例5:想要查找$HOME目录中的文件,可以用

$ find ~ name "*" -print 或 find . -print

例6:要想让系统高负荷运行,就从根目录开始查找所有的文件

$ find / -name "*" -print

例7:如果想在当前目录查找文件名以两个小写字母开头,跟着是两个数字,最后是 .txt的文件,下面的命令就能够返回例如名为 ax37.txt的文件

$ find . -name "[a-z][a-z][0-9][0-9].txt" -print
  1. 使用perm选项
    按照文件权限模式找,最好使用八进制的权限表示法

例:如在当前目录下查找权限位为755的文件,即文件属主可以读、写、执行。其他用户可以读、执行的文件,可以用:

$ find . -perm 755 -print

还有一种表示方法:在八进制数字前面要加一个横杠 - ,表示都匹配,如-077就相当于777,-006相当于666

$ find . -perm -006
  1. 忽略某个目录
    在使用 -prune选项要当心,如果同时使用了-depth选项,那么-prune选项就会被find命令忽略

例1:如果希望在/apps目录下查找文件,但不希望在/apps/bin目录下查找,可以用

$ find /apps -path "/apps/bin" -prune -o -print

例2:避开多个文件夹

$ find /home \( -path /home/itcast/f1 -o -path /home/itcast/f2 \) -prune -o print
注意:(前的\,(后的空格。      -o表逻辑或

xargs

缓冲区都撑爆,整个程序还没执行到 -exec。 因为查找结果太多,效率不高,而且进程过多,系统性能下降,而且这种方法也可能会报错——参数列表太长或参数列溢出,因为有些系统对能够传递给exec的命令长度有限制
因此,如何一边找一边执行? xargs

例1:查找系统中的每一个普通文件,然后使用xargs命令来测试它们分别属于哪类文件

# find . -type f -print | xargs file  在当前目录找,然后打印的结果 输到管道

例2:在当前目录下查找所有用户具有读、写和执行权限的文件,并收回相应的写权限

# ls -l
# find . -perm -7 -print | xargs chmod o-w
# ls -l

表明上看 和 # find . -perm -7 -print -exec chmod o-w

例3:用grep命令在所有的普通文件中搜索hello这个词

# find . -type f -print | xargs grep "hello"

例4:用grep命令在当前目录下的所有普通文件中搜索hello这个词

# find . -name \* -type f -print | xargs grep "hello"
注意: \用来取消find命令中的 * 的特殊含义

find命令配合使用exec和xargs可以使用户对所匹配到的文件执行几乎所有的命令。

sed(以行为单位处理文件)

sed意为流编辑器(Stream Editor),在Shell脚本中作为过滤器,也就是把前一个程序的输出引入sed的输入,经过一系列编辑命令转换成另一种格式输出。 以行为处理单位,匹配一行,处理一行
注意:sed命令不会修改原文件,删除命令只表示某些行不打印输出,而不是从原文件中删去

sed命令行的基本格式为

sed option 'script' file1 file2 ...     'script'过滤的正则条件
sed option -f scriptfile file1 file2 ...

选项含义:

--version           显示sed版本
--help              显示帮助文档
-n,--quiet,--silent    静默输出,默认情况下,sed程序在所有的脚本指令执行完毕后,将自动打印模式空间中的内容,这些选项可以屏蔽自动打印
-e script           允许多个脚本指令被执行
-f script-file
--file=script-file	从文件中读取脚本指令,对编写自动脚本程序来说很棒!
-i,--in-place      慎用!直接修改源文件,经过脚本指令处理后的内容将被输出至源文件(源文件被修改)
-l N,--line-length=N   该选项指令l指令可以输出的行长度,l指令为输出非打印字符。
--posix             禁用GNU sed扩展功能
-r,--regexp-extended   在脚本指令中使用扩展正则表达式,那么就不必对符号进行转义
-s,--separate      默认情况下,sed将把输入的多个文件名作为一个长的连续的输入流,而GNU sed则允许把它们当作单独的文件
-u,--unbuffered    最低限度的缓存输入和输出

简单介绍几个脚本指令操作作为sed程序的例子。

a,append         追加
i,insert         插入
d,delete         删除
s,substitution   替换

例1:$ sed “2a itcast” ./testfile   在输出testfile内容的第二行后添加 “itcast”
例2:$ sed “2,5d” testfile  在testfile的内容中 删除2到5行
 
常用的sed命令

/pattern/p   打印匹配pattern的行
/pattern/d   删除匹配pattern的行
/pattern/s/pattern1/pattern2/     查找符合pattern的行,将该行第一个匹配pattern1的字符串替换为pattern2(每行第一个)
/pattern/s/pattern1/pattern2/g    查找符合pattern的行,将该行所有匹配pattern1的字符串替换为pattern2

使用p命令需要注意,sed是把待处理文件的内容连同处理结果一起输出到标准输出的,因此p命令除了把文件内容打印出来之外还额外打印一遍匹配pattern的行。比如一个文件testfile的内容的
123
abc
456

打印其中包含abc的行

$ sed '/abc/p' testfile
123
abc
abc
456

替换

$ sed '/abc/s/b/xxx/' testfile  
123
axxxc
456

要先匹配上包含abc,之后再进行替换

注意:sed命令不会修改原文件,删除命令只表示某些行不打印输出,而不是从原文件中删去

慎用!只有-i可以修改,配合 tee使用才安全
$ sed -i "2,3d" testfile | tee ab.txt   删除2,3行,将结果输出到标准输出,另一个副本输出到相应文件

例1:要想只输出处理结果,应加上-n选项,这种用法相当于grep命令

$ sed -n '/abc/p' testfile
abc

$ sed -n '/[a-z].c/p' testfile    $ sed -n '/a.c/p' testfile 
abc

例2:使用d命令就不需要-n参数了,比如删除含有abc的行

$ sed '/abc/d' testfile
123
456

例3:使用查找替换命令时,可以把匹配pattern1的字符串复制到pattern2中,比如:

$ sed 's/bc/-&-/' testfile   直接写s,代表全局(不用匹配后)。 全局找bc的地方,然后在bc左右加-
123
a-bc-
456
  pattern2中的&表示原文件的当前行中域pattern1相匹配的字符串

例4:去除HTML标签

testfile的内容是
<html><head><title>Hello World</title></head>
<body>Welcome to the world!</body></html>

现在要去掉所有HTML,使输出结果为
Hello World
Welcome to the world!

使用以下命令:
$ sed 's/<.*>/ /g' test.txt   找<开头,.表一个字符,*匹配任意个字符,以>结尾
结果是两个空行,把所有字符都过滤掉了
这里就提到个贪婪算法,它会进行贪心匹配,一整段来看  < 中间若干字符 >

❤正确写法:$ sed 's/<[^>]*>/ /g' test.txt    [^>]表示不为>的任意一个字符

 
 

awk(以列为单位处理文件)

sed以行位单位处理文件,awk比sed强的地方在于不仅能以行位单位还能以列为单位处理文件。awk缺省的行分隔符是换行,缺省的列分隔符是连续的空格和Tab,但是行分隔符和列分隔符都可以自定义,比如/etc/passwd文件的每一行有若干个字段,字段之间以:分隔,就可以重新定义awk的列分隔符为:并以列为单位处理这个文件。awk实际上是一门很复杂的脚本语言,但是基本用法和sed类似

awk命令行的基本形式为:

awk option 'script' file1 file2 ...
awk option -f scriptfile file1 file2 ...

和sed一样,awk处理的文件既可以由标准输入重定向得到,也可以当命令行参数传入。编辑命令可以直接当命令行参数传入,也可以用-f参数指定一个脚本文件,编辑命令的格式为:

/pattern/{actions}
condition{actions}

和sed类似,pattern是正则表达式,actions是一系列操作。 awk程序一行一行读出待处理文件,如果某一行与pattern匹配,或者满足condition条件,则执行相应的actions,如果一条awk命令只有actions部分,则actions作用于待处理文件的每一行。
比如文件testfile的内容表示某商店的库存量:

ProductA  30
ProductB  76
ProductC  55

打印每一行的第二列

$ awk '{prirnt $2;}' testfile
30
76
55

❤自动变量$1、$2分别表示第一列、第二列等,类似于Shell脚本的位置参数,而 $0表示整个当前行(ProductA 30) 。再比如,如果某种产品的库存量低于75则在行末标注需要订货:

$ awk '$2<75 {printf "%s\t%s\n", $0, "REORDER";} $2>=75 {print $0;}' testfile
ProductA  30 13    REORDER
ProductB  76 46
ProductC  55 32    REORDER

可见awk也有和C语言非常相似的printf函数。awk命令的condition部分还可以是两个特殊的condition-BEGIN和END,对于每个待处理文件,BEGIN后面的actions在处理整个文件之前执行一次,END后面的actions在整个文件处理完之后执行一次。

awk命令可以像C语言一样使用变量(但不需要定义变量),比如统计一个文件中的空行数:

$ cat testfile 
ProductA  30 13
ProductB  76 46

$ awk '/^ *$/ {x=x+1;} END {print x;}' testfile    ^ 开头为空,*表零个或多个空,$表行结尾,END表文件检索完毕的时候退出做什么事,打印
2

在这里插入图片描述在这里插入图片描述
awk常用的内建变量

FILENAME   当前输入文件的文件名,该变量是只读的
NR      当前行的行号,该变量是只读的,R代表record
NF      当前行所拥有的列数,该变量是只读的,F代表field
OFS     输出格式的列分隔符,缺省是空格
FS      输入文件的列分融符,缺省是连续的空格和Tab
ORS     输出格式的行分隔符,缺省是换行符
RS      输入文件的行分隔符,缺省是换行符

❤ 例如打印系统中的用户账号列表(小面试)

$ awk 'BEGIN {FS=":"} {print "%s\t%s\n",$1,$7;}' /etc/passwd

在这里插入图片描述

发布了24 篇原创文章 · 获赞 5 · 访问量 682

猜你喜欢

转载自blog.csdn.net/qq_39578545/article/details/104902718
今日推荐