Shell编程基础教程5--文本过滤、正则表达式、相关命令

时间:2022-03-23 10:48:26

5.文本过滤、正则表达式、相关命令
    5.1.正则表达式(什么是正则表达式?正则表达式怎么进行匹配?常用命令)
        简介:
            一种用来描述文本模式的特殊语法
            由普通字符(例如字符a到z)以及特殊字符(成为元字符,如/、*、?等)组成
            匹配的字符串
            文本过滤工具在某种情况下都支持正则表达式
        基本元字符集及其含义
            ^    只匹配行首,例子 ^a 表示匹配以a开头的
            $    只匹配行尾,例子 txt$ 表示匹配以txt结尾的
            *    匹配0或多个此单字符,
            []    只匹配[]内的字符。可以是一个单字符,也可以是字符序列。可以使用-表示[]内字符序列范围,如用[1-5]代表[12345]
            \    只用来屏蔽一个元字符的特殊含义,例子 \* 可以屏蔽*作为元字符的含义,使其就表示*字符本身,\$、\^等等例子
            .    只匹配任意单字符
            pattern\{n\}    只用来匹配前面pattern出现次数。n为次数
            pattern\{n,\}    含义同上,但是次数最少为n
            pattern\{n,m\}    含义同上,但是pattern出现次数在n与m之间
        例子
            . 可以匹配任意单字符
                ...x..x..x
                    drwxrwxrw-    不匹配
                    -rw-rw-rw-    不匹配
                    -rwxr-xr-x    匹配
                    -rwxrwxrwx    匹配
                ....XC....
                    3452XC763D    匹配
                    4352XC433    不匹配
                    3452XD7654    不匹配
            ^ 只允许在一行的开始匹配字符或单词
                ^d
                    drwxrwxrw-    匹配
                    -rwxrwxr-x    不匹配
                ^...1
                    3482XC763D    不匹配
                    23DDDDxs11    不匹配
                    3451XD7633    匹配
                    3D11XC9871    匹配
            $ 与 ^ 正相反,它在行尾匹配字符串或字符,$符号放在匹配单词后面
                trouble$    匹配以单词trouble结尾的所有字符
                ^$        匹配空行
                ^.$        匹配只含有一个字符的行
            * 可以匹配任意字符0次或多次重复表达
                10133*1
                    101331        匹配
                    10133921    匹配
                    10133As1    匹配
            \ 用于屏蔽一个特殊字符
                特殊字符有",',||,^,*,+等等,元字符基本都是特殊字符
                \*\.pas        该正则表达式匹配以*.pas结尾的所有字符或文件
            [] 用于匹配一个范围或集合
                逗号将括号内要匹配的不同字符串分开
                用 - 表示一个字符串范围,表明字符串范围从 - 左边字符开始,到 - 右边字符结束
                例子
                    [0123456789]或[0-9]        假定要匹配任意一个数字
                    [a-z]    任意小写字母
                    [A-Za-z]    任意大小写字母
                    [A-Za-z0-9]        匹配任意字母或数字
                    [S,s]    匹配大小写s
            \{\} 用于匹配模式结果出现的次数
                A\{2\}B        A出现2次,AAB
                A\{4,\}B    A至少出现4次,AAAAB、AAAAAB……
                A\{2,4\}B    A出此案次数为2到4次,AAB、AAAB、AAAAB
                [0-9]\{3\}\.[0-9]\{3\}\.[0-9]\{3\}\.[0-9]\{3\}    匹配IP地址
    5.2.find介绍(文件查找)
        简介
            一个查找命令
            查找具有某些特征文件的命令
            可遍历当前目录甚至整个文件系统来查找某些文件或目录
            遍历大的文件系统时,因为耗时比较长,一般放在后台执行,并将结果重定向到一个文件
        命令格式
            find pathname -options [-print -exec -ok]
                pathname    find命令所查找的目录路径。例如用.表示当前目录,用/来表示系统根目录
                -print    find命令将匹配的文件输出到标准输出
                -exec    find命令将匹配的文件执行该参数所给出的shell命令,相应命令的形式为 command {} \; 。注意{}和\;之间的空格
                -ok和-exec的作用相同,只不过以一种更为安全的模式来执行该参数所给出的shell命令,在执行每一个命令之前,都会给出体术,让用户来确定是否执行
        find的命令选项
            -name    按照文件名查找文件
            -perm    按照文件权限来查找文件
            -user    按照文件属主来查找文件
            -group    按照文件所属的组来查找文件
            -mtime -n +n    按照文件的更改时间来查找文件,-n表示文件更改时间距离现在n天以内, +n 表示文件更改时间距离现在n天以前。find命令还有-atime和-ctime选项,但是它们都和-mtime选项相似
            -size n[c]    查找文件长度为n块的文件,带有 c 时表示文件长度以字节计
            -nogroup    查找无有效所属组的文件,即该文件所述的组在/etc/groups中不存在
            -nouser        查找无有效数组的文件,即该文件的属主在/etc/passwd中不存在
            -newer "file1" ! -newer "file2"        查找更改时间比文件file1新但是比file2旧的文件
            -type    查找某一类型的文件,例如:
                b    块设备文件
                d    目录
                c    字符设备文件
                p    管道文件
                l    符号链接文件
                f    普通文件
            man find 来查看更多更为详细的关于find命令的信息
        示例:
            使用name选项
                可以使用某种文件名模式来匹配文件,记住要用引号将文件名模式引起来
                find -name "*.txt" -print        没写任何路径,就是默认当前路径
                find ./ -name "*.txt" -print
                find ./ -name "[A-Z]*" -print
                find /etc -name "host*" -print
            使用perm选项
                find ./ -perm 755 -print
            使用user和nouser选项
                find `pwd` -user root -print    反引号里的命令,`pwd`表示执行pwd命令获取的路径作为find查找的路径
                find / -nouser -print
                nohup find / -nouser -print > nouser.log    在后台执行(使用nohup)find命令,并将结果重定向到nouser.log文件中
            使用group和nogroup
                find ./ -group perfect -print
                find / -nogroup -print
            按照更改时间查找文件
                find /var -mtime -5 -print
                find /var/ -mtime +3 -print
            查找比某个文件新或旧的文件
                find `pwd` -newer "myfile" ! -new "myfile123" -print
            使用type选项
                find /etc -type d -print
                find /etc -type l -print
            使用size选项
                find ./ -size +1000000c -print    c表示单位是字符、字节
                find ./ -size +10 -print    没有c表示单位是块
            使用depth选项
                使用find命令时,可能希望先匹配所有的文件,再在子目录里查找
                find / -name "CON.FILE" -depth -print
            使用exec或ok来执行shell命令
                find ./ -type f -exec ls -l{} \;    查找本目录下的所有的普通文件,并逐个对查找出来的这些文件进行ls -l操作
                find ./ -name "*.log" -mtime +5 -ok rm{} \;    常用于删除一定天数之前的日志文件
            xargs命令
                在使用find命令的-exec选项处理匹配到的文件时,find命令将所有匹配到的文件一起传递给exec。不幸的是,有些系统对能够传递给-exec的命令长度有限制,这样在find命令运行几分钟之后,就会出现一处错误。错误信息通常是“参数列太长”或者“参数列溢出”。这就是xargs命令的用处所在,特别是与find命令一起使用。-exec会发起多个进程,而xargs不会多个,只用一个,就会减少系统资源的消耗
                    find ./ -perm -7 -print | xargs chmod o-w    xargs的作用是将 find ./ -perm -7 -print 的结果传给 chmod o-w 命令来进行执行
                    find ./ -type f print | xargs file
    5.3.grep介绍(文本过滤)
        简介:
            grep是Unix和Linux中使用最广泛的命令之一
            对文本文件进行模式查找
            对文本进行按行的匹配
            grep有三种变形
                Grep:标砖grep命令
                Egrep:扩展grep,支持基本以及扩展的正则表达式
                Fgrep:快速grep
        grep一般格式:
            grep [选项] 基本正则表达式 [文件]
            其中基本正则表达式最好采用双引号括起来,一是防止被误认为是shell命令,二是可以用来查找多个单词组成的字符串
        grep命令选项
            -c    只输出匹配行的计数
            -i    不区分大小写(只适用于单字符)
            -h    查询多文件时不显示文件名
            -H    查询多文件时显示文件名
            -l    查询多文件时只输出包含匹配字符的文件名
            -n    显示匹配行及行号
            -s    不显示不存在或无匹配文本的错误信息
            -v    显示不包含匹配文本的所有行,功能就是过滤某些文本
        例子
            grep "jenny" *.txt    从所有 txt 文件中查找存在 jenny 的行有哪些
            grep "sort it" *    在所有文件中查找存在 sort it 的行有哪些
            grep -c "2004" myfile    输出 myfile 中有多少行匹配到 2004
            grep -n "2004" myfile    输出 myfile 中匹配 2004 的行及行号
            grep -i "Jul" myfile    输出 myfile 中匹配 Jul 的行,Jul 不区分大小写
            grep -v "2004:22" myfile    过滤掉myfile中含有 2004:22 的行,只输出不含有 2004:22 的行
            grep "2004:22:5[0-9]" myfile    输出 myfile 中含有 2004:22:50 到 2004:22:59 的行
            grep "^[^210]" myfile    输出 myfile 中开头不是 2 也不是 1 也不是 0 的行
            grep "H*P" myfile    输出匹配正则表达式 H*P 模式的行
            grep "[5-8][6-9][0-3]" myfile
            grep "4\{2\}" myfile
            grep "4\{2,\}" myfile
            grep "4\{2,4\}" myfile    输出匹配正则表达式 4\{2,4\} 模式的行,该模式的含义是 4 连续出现的次数是 2到4 次
            grep "^$" myfile    输出匹配正则表达式 ^$ 模式的行,^$ 的含义是空行
            grep "\?" myfile    \? 转义 ?
            grep "^d" lsout.txt        ^d 表示以 d 开头
            grep "^[^d]" lsout.txt        ^[^d] 表示不以d开头
        grep命令类名和等价的正则表达式
            [[:upper:]]        [A-Z]
            [[:alnum:]]        [0-9a-zA-Z]
            [[:lower:]]        [a-z]
            [[:space:]]        空格或tab键
            [[:digit:]]        [0-9]
            [[:alpha:]]        [a-zA-Z]
            例子
                grep "5[[:digit:]][[:digit:]]" myfile    其中的正则表达式表示 500 到 599 的数字范围
    5.4.awk介绍
        简介:
            可从文件或字符串中基于指定规则浏览和抽取信息
            是一种自解释的编程语言
            三种方式调用awk:
                命令行方式:awk [-F filed-spearator] 'command' input-files
                awk脚本:所有awk命令插入一个文件,并令awk程序可执行,然后用awk命令解释器作为脚本的首行,以便通过键入脚本名称来调用它
                awk命令插入一个单独文件:awk -f awk-script-file input-files
            awk脚本由各种操作和模式组成
            模式和动作:
                模式部分决定动作语句何时触发及出发事件(BEGIN,END)
                动作对数据进行处理,放在大括号{}内指明(print)
            分隔符、域和记录
                awk执行时,其浏览域标记为$1、$2....$n。这种方法称为域标识。$0为所有域
                    例如一行数据 2005 computer is expensive ,默认分隔符是 空格,那么这一行就有4个域,第一个是 2005,第二个是 computer,第三个是 is,第四个是 expensive
                注意执行时不要混淆符号 $ 和 shell提示符 $ ,它们是不同的
        例子1:
            awk '{print $0}' score.txt | tee score.out        将score.txt文件中的所有信息打印出来,在屏幕上输出信息,并且也将信息输入到score.out文件中
            awk -F : '{print $1"\t"$4}' score.txt        注意 -F : 作用是将分隔符从默认分隔符 空格 变成 : ,这条命令表示在屏幕上输出 score.txt 文件中以:为分隔符分割后每行中第一个域和第四个域的内容,第一个域和第四个域的内容在输出信息中以 \t 也就是 tab跳隔符分割,在输出域的时候,分隔符:不会输出
            awk 'BEGIN {print "IP Date\n--------"}{print $1"\t"$4}END{"end-of-report"}' score.txt    BEGIN {print "IP Date\n--------"}打印一些报告头,END{"end-of-report"}打印一些报告尾,{print $1"\t"$4}打印在score.txt中模式匹配的主体信息
        awk特殊字符
            awk中的特殊字符:+、?,+表示匹配任意字符,?表示匹配单个字符
            匹配操作符:~、!~,~表示匹配,!~表示不匹配
        例子2:
            cat score.txt | awk '$0~/218.79.13.196/'    在score.txt中查找出所有匹配 218.79.13.196 的行,注意匹配模式放在//里面
            awk '$1!~/218.79.13.196/' score.txt        在score.txt中,以默认分隔符空格来划分每一行,输出第一个域不匹配(!~)218.79.13.196的行
            awk '{if($1=="218.79.131.96") print $0}' score.txt        在score.txt中,以默认分隔符空格来划分每一行,如果(if)第一个域($1)等于(==)218.79.13.196,就打印这一行的所有信息(也就是这一行的所有域$0)
    5.5.sed介绍
        简介:
            sed不与初始化文件打交道,也就是绝对不会更改原文件的内容,它操作的只是一个拷贝,然后所有的改动如果没有重定向到一个文件,将输出到屏幕
            sed是一个重要的文本过滤工具,使用一行命令或者使用管道与grep与awk相结合
            非交互性文本流编辑
        调用sed的三种方式
            使用sed命令行格式为:sed [选项] sed命令 输入文件
            使用sed脚本文件格式为:sed [选项] -f sed脚本文件 输入文件
            sed脚本文件 [选项] 输入文件
            补充:不管是使用shell命令行方式或是脚本文件方式,如果没有指定输入文件,sed从标准输入中接受输入,一般是键盘或重定向结果
        sed命令选项如下:
            -n    不打印没匹配到的行
            -c    下一命令是编辑命令
            -f    如果正在调用sed脚本文件
        sed在文件中查询文本的方式
            使用行号,可以是一个简单数字,或是一个行号范围
                x        x为一行好
                x,y        表示行号范围从x到y
            使用正则表达式
                /pattern/        查询包含模式的行
                /pattern/pattern/    查询包含两个模式的行
                /pattern/,x        在给定行号上查询包含模式的行
                x,/pattern/        通过行号和模式查询匹配行,从第x行开始一直匹配到有/pattern/的行结束
                x,y!            查询不包含执行行号x和y的行
        基本sed编辑命令
            p    打印匹配行
            =    显示文件名
            a\    在定位行号后附加新文本信息
            i\    在定位行号前附加新文本信息
            d    删除定位行
            c\    用新文本替换定位文本
            s    使用替换模式替换相应模式
            r    从另一个文件中读文本
            w    写文本到一个文件
            q    第一个模式匹配完成后退出或立即退出
            l    显示与八进制ASCII代码等价的控制字符
            {}    在定位行执行的命令组
            n    从另一个文件中读文本下一行,并附加在下一行
            g    将模式2粘贴到/pattern n/
            y    传送字符
        例子:
            sed '2p' score.txt        基本sed编辑命令p表示打印匹配行,所以这句就是打印第2行,但是没有-n(-n指的是不打印没匹配的行),所以还是会打印所有的行
            sed -n '2p' score.txt        基本sed编辑命令p表示打印匹配行,而且还有-n参数,所以这句就是打印第2行
            sed -n '1,4p' score.txt        基本sed编辑命令p表示打印匹配行,所以 1,4p 表示打印第1到第4行,-n表示不打印不匹配的行
            sed -n '/los/p' myfile.txt        -n表示不打印不匹配的行,所以就是打印匹配 los 字符串的行,以为/los/后有p编辑命令,就是打印匹配行
            sed -n '4,/los/' myfile.txt
            sed -n '/^$/=' myfile
            sed -n -e '/^$/p' -e '/^$=' myfile
            sed -n '/chinaitlab/a\shenzhen' myfile.txt
            sed -n '/chinaitlab/i\shenzhen' myfile.txt
            sed -n '/chinaitlab/c\chinaitlab shenzhen' myfile.txt
            sed '1,2d, myfile.txt        删除1到2行的内容
            sed 's/chinaitlab/chinaitlab shenzhen/g' myfile.txt
            sed -n 's/chinaitlab/& hello/p' myfile.txt        在有chinaitlab的行前面插入 hello
            sed -n 's/chinaitlab/hello &/p' myfile.txt        在有chinaitlab的行后面插入 hello
            sed 'lr ctrl.txt' myfile.txt
            sed '/china/q' myfile.txt
            sed -n '/china/l' myfile.txt
    5.6.合并与分割(sort、uniq、join、cut、paste、split)
        sort [options] files
            许多不同的域按照不同的列顺序排序
            -c    测试文件是否已经分类
            -m    合并两个分类文件
            -u    删除所有复制行
            -o    存储sort结果的输出文件名
            -t    域分隔符;用非空格或tab键分隔域
            +n    n为域名,使用此域名开始分类,sort中的域是从0开始的,不同于awk(awk的域是从1开始的,0表示所有域)
            n    指定分类是域上的数字分类项
            -r    比较逆序
            例子:
                sort -c myfile        检查myfile有没有排序
                sort -u myfile        如果myfile有重复的行,就合并这些行为一行
                sort -r myfile        以逆序排序
                sort -t "/" +2 myfile        以/作为分隔符,并以第2个域来排序
                sort -t "/" +2n myfile        以/作为分隔符,并以第2个域按数字排序,+2n中的 n 就是指按数字排序,如果没有n,那么173排在19的后面,因为是逐个比较每个字符,如果有n,就是比较数字173和19的大小来排序
        uniq [options] files
            从一个文本文件中去除或禁止重复行,关于重复的行,统计只对邻近的行有效
            -u    只显示不重复行
            -d    只显示有重复数据行,每种重复行只显示其中一行
            -c    打印每一重复行出现次数
            -f n    n为数字,前n个域被忽略,只比较第n以及第n之后的域,如果某一行域的个数少于n,就不输出该行
            例子:
                uniq -c myfile.txt        
                uniq -d myfile.txt
                uniq -f 2 myfile.txt
                uniq -d myfile.txt
        join [options] file1 file2
            用来讲来自两个分类文本文件的行连接在一起
            -an        n为数字,用于连接时从文件n中显示不匹配行
            -o n.m     连接域,n为文件名,m为域名
            -j n m    n为文件名,m为域名。使用其他域做连接域
            t        域分隔符,用来设置非空格或tab键的域分隔符
            例子
                join -a1 -a2 address.txt town
                join -o 2.2,1.1    address.txt town
                join -j1 1 -j2 1 address.txt town
        split
            用于将大文件分割成小文件
            命令格式
                split -output_file-size input-filename output-filename
                -b n    每个分割文件的大小为n(k,m)
                -C n    每个分割文件一行最多n个字节数
                -l n    每个分割文件的行数
                -n        同-l n
            例子
                split -10 ls_out.txt split
        cut
            用于从标准输入或文本文件中剪切列或域
        paste
            将按行将不同文件行信息放在一行