find、sed、grep、awk

一、前言

  这四个命令可谓是常用的4个文本处理工具,本篇记录各自的用法。

二、find 

  find通常用于查找文件或命令。

2.1 find命令一般形式

   find命令的常用形式可以简化为:

   find [path...] [expression]

   1)path:find命令所查找的目录路径。例如用.来表示当前目录,用/来表示系统根目录

   2)expression:expression可以分为——“-options [-print -exec -ok ...]”

   3)-options,指定find命令的常用选项,下节详细介绍

   4)-print,find命令将匹配的文件输出到标准输出

   5)-exec,find命令对匹配的文件执行该参数所给出的shell命令。相应命令的形式为'command' {  } \;,注意{   }和\;之间的空格,

    例如find ./ -size 0 -exec rm {} \; 删除文件大小为零的文件,当然也可以管道和xargs联合使用(find ./ -size 0 | xargs rm -f &);

    为了用ls -l命令列出所匹配到的文件,可以把ls -l命令放在find命令的-exec选项中:find . -type f -exec ls -l {  } \; 

    在/logs目录中查找更改时间在5日以前的文件并删除它们:find /logs -type f -mtime +5 -exec rm {  } \; 

   6)-ok,和-exec的作用相同,只不过以一种更为安全的模式来执行该参数所给出的shell命令,在执行每一个命令之前,都会给出提示,让用户来确定是否执行。

    find . -name "*.conf"  -mtime +5 -ok rm {  } \; 在当前目录中查找所有文件名以.LOG结尾、更改时间在5日以上的文件,并删除它们,只不过在删除之前先给出提示

2.2 find命令的常用选项及实例

   1)-name

    按照文件名查找文件。 

    find /dir -name filename  在/dir目录及其子目录下面查找名字为filename的文件 

    find . -name "*.c" 在当前目录及其子目录(用“.”表示)中查找任何扩展名为“c”的文件

   2)-perm

    按照文件权限来查找文件。 

    find . -perm 755 –print 在当前目录下查找文件权限位为755的文件,即文件属主可以读、写、执行,其他用户可以读、执行的文件

   3)-prune 

    使用这一选项可以使find命令不在当前指定的目录中查找,如果同时使用-depth选项,那么-prune将被find命令忽略。 

    find /apps -path "/apps/bin" -prune -o –print 在/apps目录下查找文件,但不希望在/apps/bin目录下查找 

    find /usr/sam -path "/usr/sam/dir1" -prune -o –print 在/usr/sam目录下查找不在dir1子目录之内的所有文件

   4)-user 

    按照文件属主来查找文件。

            find ~ -user sam –print 在$HOME目录中查找文件属主为sam的文件

          5)-group 

            按照文件所属的组来查找文件。 

            find /apps -group gem –print 在/apps目录下查找属于gem用户组的文件

          6)-mtime -n +n 

            按照文件的更改时间来查找文件, - n表示文件更改时间距现在n天以内,+ n表示文件更改时间距现在n天以前。 

            find / -mtime -5 –print 在系统根目录下查找更改时间在5日以内的文件 

            find /var/adm -mtime +3 –print 在/var/adm目录下查找更改时间在3日以前的文件

          7)-nogroup 

            查找无有效所属组的文件,即该文件所属的组在/etc/groups中不存在。 

            find / –nogroup -print

          8)-nouser 

            查找无有效属主的文件,即该文件的属主在/etc/passwd中不存在。 

            find /home -nouser –print

          9)-newer file1 ! file2 

            查找更改时间比文件file1新但比文件file2旧的文件。

         10)-type 

            查找某一类型的文件,诸如: 

            b - 块设备文件。       

           d - 目录。 

            c - 字符设备文件。 

            p - 管道文件。 

            l - 符号链接文件。 

            f - 普通文件。

            find /etc -type d –print 在/etc目录下查找所有的目录 

            find . ! -type d –print 在当前目录下查找除目录以外的所有类型的文件 

            find /etc -type l –print 在/etc目录下查找所有的符号链接文件

         11)-size n:[c] 查找文件长度为n块的文件,带有c时表示文件长度以字节计。

            find . -size +1000000c –print 在当前目录下查找文件长度大于1 M字节的文件 

            find /home/apache -size 100c –print 在/home/apache目录下查找文件长度恰好为100字节的文件 

            find . -size +10 –print 在当前目录下查找长度超过10块的文件(一块等于512字节)

         12)-depth:在查找文件时,首先查找当前目录中的文件,然后再在其子目录中查找。 

            find / -name "CON.FILE" -depth –print 它将首先匹配所有的文件然后再进入子目录中查找 

         13)-mount:在查找文件时不跨越文件系统mount点。

            find . -name "*.XC" -mount –print 从当前目录开始查找位于本文件系统中文件名以XC结尾的文件(不进入其他文件系统)

         14)-follow:如果find命令遇到符号链接文件,就跟踪至链接所指向的文件。

2.2  find与xargs

         在使用find命令的-exec选项处理匹配到的文件时, find命令将所有匹配到的文件一起传递给exec执行。但有些系统对能够传递给exec的命令长度有限制,这样在find命令运行几分钟之后,就会出现溢出错误。错误信息通常是“参数列太长”或“参数列溢出”。这就是xargs命令的用处所在,特别是与find命令一起使用。

         find命令把匹配到的文件传递给xargs命令,而xargs命令每次只获取一部分文件而不是全部,不像-exec选项那样。这样它可以先处理最先获取的一部分文件,然后是下一批,并如此继续下去。

         在有些系统中,使用-exec选项会为处理每一个匹配到的文件而发起一个相应的进程,并非将匹配到的文件全部作为参数一次执行;这样在有些情况下就会出现进程过多,系统性能下降的问题,因而效率不高;

         而使用xargs命令则只有一个进程。另外,在使用xargs命令时,究竟是一次获取所有的参数,还是分批取得参数,以及每一次获取参数的数目都会根据该命令的选项及系统内核中相应的可调参数来确定。

        来看看xargs命令是如何同find命令一起使用的,并给出一些例子

        find . -type f -print | xargs file 查找系统中的每一个普通文件,然后使用xargs命令来测试它们分别属于哪类文件

        find / -name "core" -print | xargs echo "" >/tmp/core.log 在整个系统中查找内存信息转储文件(core dump) ,然后把结果保存到/tmp/core.log 文件中:

        find . -type f -print | xargs grep "hostname" 用grep命令在所有的普通文件中搜索hostname这个词  

        find ./ -mtime +3 -print|xargs rm -f –r 删除3天以前的所有东西 (find . -ctime +3 -exec rm -rf {} \;)

        find ./ -size 0 | xargs rm -f & 删除文件大小为零的文件

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

三、grep

        grep即 (global search regular expression(RE) and print out the line,全面搜索正则表达式并把行打印出来)是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来。

3.1 grep命令一般选项

        grep [OPTIONS] PATTERN [FILE...] 

        grep [OPTIONS] [-e PATTERN | -f FILE] [FILE...]

        grep命令用于搜索由Pattern参数指定的模式,并将每个匹配的行写入标准输出中。这些模式是具有限定的正则表达式,它们使用ed或egrep命令样式。

3.2  grep命令常用OPTIONS

        ^  锚定行的开始 如:'^grep'匹配所有以grep开头的行。

        $  锚定行的结束 如:'grep$'匹配所有以grep结尾的行。

        .   匹配一个非换行符的字符 如:'gr.p'匹配gr后接一个任意字符,然后是p。

        *  匹配零个或多个先前字符 如:' *grep'匹配所有一个或多个空格后紧跟grep的行。 .*一起用代表任意字符。

        [] 匹配一个指定范围内的字符,如'[Gg]rep'匹配Grep和grep。

        [^]  匹配一个不在指定范围内的字符,如:'[^A-FH-Z]rep'匹配不包含A-F和H-Z的一个字母开头,紧跟rep的行。

        \(..\)  标记匹配字符,如:'\(love\)',love被标记为1。

        \<  锚定单词的开始,如:'\<grep'匹配包含以grep开头的单词的行。

        \>  锚定单词的结束,如'grep\>'匹配包含以grep结尾的单词的行。

        x\{m\} 连续重复字符x,m次,如:'o\{5\}'匹配包含连续5个o的行。

        x\{m,\} 连续重复字符x,至少m次,如:'o\{5,\}'匹配至少连续有5个o的行。

        x\{m,n\} 连续重复字符x,至少m次,不多于n次,如:'o\{5,10\}'匹配连续5--10个o的行。

        \w  匹配一个文字和数字字符,也就是[A-Za-z0-9],如:'G\w*p'匹配以G后跟零个或多个文字或数字字符,然后是p。

        \W  w的反置形式,匹配一个非单词字符,如点号句号等。\W*则可匹配多个。

        \b  单词锁定符,如: '\bgrep\b'只匹配grep,即只能是grep这个单词,两边均为空格。

3.3  grep命令常用PATTERN 

        -?

       同时显示匹配行上下的?行,如:grep -2 pattern filename同时显示匹配行的上下2行。

       -b,--byte-offset

       打印匹配行前面打印该行所在的块号码。

       -c,--count

       只打印匹配的行数,不显示匹配的内容。

       -f File,--file=File

       从文件中提取模板。空文件中包含0个模板,所以什么都不匹配。

       -h,--no-filename

        当搜索多个文件时,不显示匹配文件名前缀。

       -i,--ignore-case

       忽略大小写差别。

       -q,--quiet

       取消显示,只返回退出状态。0则表示找到了匹配的行。

       -l,--files-with-matches

       打印匹配模板的文件清单。

       -L,--files-without-match

       打印不匹配模板的文件清单。

       -n,--line-number

       在匹配的行前面打印行号。

       -s,--silent

        不显示关于不存在或者无法读取文件的错误信息。

        -v,--revert-match

        反检索,只显示不匹配的行。

        -w,--word-regexp

        如果被\<和\>引用,就把表达式做为一个单词搜索。

        -V,--version

        显示软件版本信息。

3.4  grep命令常用PATTERN 

        ls -l | grep '^a' 通过管道过滤ls -l输出的内容,只显示以a开头的行。

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

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

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

        grep 'w(es)t.*' aa 如果west被匹配,则es就被存储到内存中,并标记为1,然后搜索任意个字符(.*),这些字符后面紧跟着另外一个es(),找到就显示该行。如果用egrep或 grep -E,就不用""号进行转义,直接写成'w(es)t.*'就可以了。

        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 pattern1 files | grep pattern2 :显示既匹配 pattern1 又匹配 pattern2 的行。

        grep -i -n -R 'zjy'  /home :搜索home目录及子目录下存在 'zjy'(不分大小写) 的行(标出行号),

四、sed

        sed是一个很好的文件处理工具,本身是一个管道命令,主要是以行为单位进行处理,可以将数据行进行替换、删除、新增、选取等特定工作

        sed常用命令选项

        sed [-nefri] ‘command’ 输入文本 

常用选项:

         -n∶使用安静(silent)模式。在一般 sed 的用法中,所有来自 STDIN的资料一般都会被列出到萤幕上。但如果加上 -n 参数后,则只有经过sed 特殊处理的那一行(或者动作)才会被列出来。

        -e∶直接在指令列模式上进行 sed 的动作编辑;

        -f∶直接将 sed 的动作写在一个档案内, -f filename 则可以执行 filename 内的sed 动作;

        -r∶sed 的动作支援的是延伸型正规表示法的语法。(预设是基础正规表示法语法)

        -i∶直接修改读取的档案内容,而不是由萤幕输出。       

常用命令:

        a∶新增, a 的后面可以接字串,而这些字串会在新的一行出现(目前的下一行)

        c∶取代, c 的后面可以接字串,这些字串可以取代 n1,n2 之间的行!

        d∶删除,因为是删除啊,所以 d 后面通常不接任何咚咚;

         i ∶插入, i 的后面可以接字串,而这些字串会在新的一行出现(目前的上一行);

        p∶列印,亦即将某个选择的资料印出。通常 p 会与参数 sed -n 一起运作~

        s ∶取代,可以直接进行取代的工作哩!通常这个 s 的动作可以搭配正规表示法!例如 1,20s/old/new/g 就是啦!        

举例:(假设我们有一文件名为ab)

         1) 删除某行(ab为某个文件)

         # sed '1d' ab              #删除第一行 

         # sed '$d' ab              #删除最后一行

         # sed '1,2d' ab           #删除第一行到第二行

         # sed '2,$d' ab           #删除第二行到最后一行

         2) 显示某行

         # sed -n '1p' ab           #显示第一行

         # sed -n '$p' ab           #显示最后一行

         # sed -n '1,2p' ab        #显示第一行到第二行

         # sed -n '2,$p' ab        #显示第二行到最后一行

         3) 使用模式进行查询

          # sed -n '/ruby/p' ab    #查询包括关键字ruby所在所有行

          # sed -n '/\$/p' ab        #查询包括关键字$所在所有行,使用反斜线\屏蔽特殊含义

         4) 增加一行或多行字符串(假设下列 ab为一个文件)

          # sed '1a drink tea' ab  

          # sed '1,3a drink tea' ab #第一行到第三行后增加字符串"drink tea"

          # sed '1a drink tea\nor coffee' ab   #第一行后增加多行,使用换行符\n

          5) 代替一行或多行

          # sed '1c Hi' ab                #第一行代替为Hi

          # sed '1,2c Hi' ab             #第一行到第二行代替为Hi

          6) 替换一行中的某部分

          格式:sed 's/要替换的字符串/新的字符串/g'   (要替换的字符串可以用正则表达式)

          # sed -n '/ruby/p' ab | sed 's/ruby/bird/g'    #替换ruby为bird

          # sed -n '/ruby/p' ab | sed 's/ruby//g'        #删除ruby

          7) 插入

          # sed -i '$a bye' ab         #在文件ab中最后一行直接输入"bye

          8) 删除匹配行

          sed -i '/匹配字符串/d'  filename  (注:若匹配字符串是变量,则需要“”,而不是‘’。记得好像是)

          替换匹配行中的某个字符串

           sed -i '/匹配字符串/s/替换源字符串/替换目标字符串/g' filename

          如 sed -i '/mario/s/abc/def/g' readme.txt  , 就是将包含字符串mario的所在行,将abc替换为def

五、awk

          awk就是把文件逐行的读入,以空格为默认分隔符或设置的分隔符将每行切片,切开的部分再进行各种分析处理。

          awk的命令行方式为:

          awk [-F  field-separator]  'commands'  input-file(s)

          上式中field-separator 为域分隔符,[-F  域分隔符] 可以不选,不选就默认是空格,commands 是真正awk命令,input-file(s) 是待处理的文件。在awk中,文件的每一行中,由域分隔符分开的每一项称为一个域

5.1、awk实例

         awk工作流程是这样的:读入有'\n'换行符分割的一条记录,然后将记录按指定的域分隔符划分域,填充域,$0则表示所有域,$1表示第一个域,$n表示第n个域。默认域分隔符是"空白键" 或 "[tab]键",所以$1表示登录用户,$3表示登录用户ip,以此类推

         1) 例如显示/etc/passwd的账户的第一个段

         #cat /etc/passwd |awk  -F ':'  '{print $1}'  

         2) 如果只是显示/etc/passwd的账户和账户对应的shell,而账户与shell之间以tab键分割

         #cat /etc/passwd |awk  -F ':'  '{print $1"\t"$7}'

         3) 如果只是显示/etc/passwd的账户和账户对应的shell,而账户与shell之间以逗号分割,而且在所有行添加列名name,shell,在最后一行添加"blue,/bin/nosh"。

         cat /etc/passwd |awk  -F ':'  'BEGIN {print "name,shell"}  {print $1","$7} END {print "blue,/bin/nosh"}'

         awk工作流程是这样的:先执行BEGING,然后读取文件,读入有/n换行符分割的一条记录,然后将记录按指定的域分隔符划分域,填充域,$0则表示所有域,$1表示第一个域,$n表示第n个域,随后开始执行模式所对应的动作action。接着开始读入第二条记录······直到所有的记录都读完,最后执行END操作。

         awk内置变量

         ARGC               命令行参数个数

         ARGV               命令行参数排列

         ENVIRON            支持队列中系统环境变量的使用

         FILENAME           awk浏览的文件名

         FNR                浏览文件的记录数

         FS                 设置输入域分隔符,等价于命令行 -F选项

         NF                 浏览记录的域的个数

         NR                 已读的记录数

         OFS                输出域分隔符

         ORS                输出记录分隔符

         RS                 控制记录分隔符

        统计/etc/passwd:文件名,每行的行号,每行的列数,对应的完整行内容

        #awk  -F ':'  '{print "filename:" FILENAME ",linenumber:" NR ",columns:" NF ",linecontent:"$0}' /etc/passwd

        使用printf替代print,可以让代码更加简洁,易读

        awk  -F ':'  '{printf("filename:%10s,linenumber:%s,columns:%s,linecontent:%s\n",FILENAME,NR,NF,$0)}' /etc/passwd

        更多请查看参考文献

六、参考文献

find 、grep 出自 https://www.cnblogs.com/skynet/archive/2010/12/25/1916873.html

sed 出自 https://www.cnblogs.com/dong008259/archive/2011/12/07/2279897.html

awk 出自  https://www.cnblogs.com/ggjucheng/archive/2013/01/13/2858470.html


猜你喜欢

转载自blog.csdn.net/AP1005834/article/details/78622007