【shell笔记>命令】grep,sed,awk

作者: 王诗翔 | 来源:发表于2017-04-09 19:01 被阅读328次

    grep

    grep的基本用法

    grep命令是支持正则表达式的一个多用途文本搜索工具,一般格式为

    grep 选项 模式 文件

    选项 意义
    -c 只输出匹配行的数量
    -i 搜索时忽略大小写
    -h 查询多文件时不显示文件名
    -l 只列出符合匹配的文件名,而不列出具体的匹配行
    -n 列出所有的匹配行,并显示行号
    -s 不显示不存在或无匹配文本的错误信息
    -v 显示不包含匹配文本的所有行
    -w 匹配整词
    -x 匹配正行
    -r 递归搜索,不仅搜索当前目录,而且搜索子目录
    -q 禁止输出任何结果,以退出状态表示搜索是否成功
    -b 打印匹配行距文件头部的偏移量,以字节为单位
    -o 与-b选项结合使用,打印匹配的词距文件头部的偏移量,以字节为单位
    -E 支持扩展的正则表达式
    -F 不支持正则表达式,按照字符串的字面意思进行匹配

    grep命令的模式十分灵活,可以是字符串,也可以是变量,还可以是正则表达式。注意,无论模式是何种形式,只要模式中包含空格,就需要使用双引号将模式引起来。

    grep与正则表达式

    1. 匹配行首,用元字符^
    1. 设置大小写,用-i

    2. 匹配重复字符,用., *

    3. 转义符,用\

    4. POSIX字符类

      类名 意义
      [:upper:] 表示大写字母[A~Z]
      [:lower:] 表示小写字母[a~z]
      [:digit:] 表示阿拉伯数字[0~9]
      [:alnum:] 表示大小写字母和阿拉伯数字
      [:space:] 表示空格键和TAB键
      [:alpha:] 表示大小写字母
      [:cntrl:] 表示Ctrl
      [:graph:]或[:print:] 表示ASCII码
      [:xdigit:] 表示16进制数字[09AFa~f]
    5. 精确匹配:用\<\>

    6. 或字符,grep需要加上-E选项才能支持它,用|表示

    grep命令族

    grep: 标准grep命令

    egrep: 扩展grep命令,支持基本和拓展正则表达式

    fgrep: 快速grep命令,不支持正则表达式


    sed命令

    sed是一个非交互式文本编辑器,它可对文本文件和标准输入进行编辑,标准输入可以是来自键盘输入、文件重定向、字符串、变量,甚至来自管道的文本。sed适用于以下三中场合:

    • 编辑相对交互式文本编辑器而言太大的文件。
    • 编辑命令太复杂,在交互式文本编辑器中难以输入的情况。
    • 对文件扫描一遍,但是需要执行多个编辑函数的情况。

    基本用法

    sed只是对缓冲区中原始文件的副本进行编辑,并不编辑原始文件。如果需要保存文件改动的内容,需要将输出重定向到另一个文件。

    调用sed有三种方式,一种为Shell命令行方式,另外两种是将sed命令写入脚本文件,然后执行该脚本文件。

    1. 在Shell命令行输入命令调用sed,格式为sed [选项] 'sed命令' 输入文件
    2. sed命令插入脚本文件后,然后通过sed命令调用它,格式为sed [选项] -f sed 脚本文件 输入文件
    3. sed命令插入脚本文件后,最常用的方法是设置该脚本文件为可以执行,然后直接执行该脚本文件,格式为./sed脚本文件 输入文件

    第三种方式脚本文件需要以sha-bang(#!)符号开头。无论哪种方式,如果没有指定输入文件,sed将从标准输入接收输入。常用选项有三个

    选项 意义
    -n 不打印所有的行到标准输出
    -e 表示将下一个字符串解析为sed编辑命令,如果只传递一个,可以省略
    -f 表示正在调用sed脚本文件

    sed命令主要由定位文本行和sed编辑命令两部分组成,有两种方式定位文本:

    • 使用行号,指定一行,或者指定行号范围
    • 用正则表达式
    选项 意义
    x x为指定行号
    x,y 指定从x到y的行号范围
    /pattern/ 查询包含模式的行
    /pattern/pattern/ 查询包含两个模式的行
    /pattern/,x 从pattern匹配行到x号行
    x,/pattern/ 上一条反过来
    x,y! 查询不包括x和y行号的行

    编辑命令

    选项 意义
    p 打印匹配行
    = 打印文件行号
    a\ 在定位行号后追加文本信息
    i\ 在定位行号之前插入文本信息
    d 删除定位行
    c\ 用新文本替代定位文本
    s 使用替换模式替换相应模式
    r 从另一个文件中读文本
    w 将文本写入到一个文件
    y 变换字符
    q 第一个模式匹配后退出
    l 显示与八进制ASCII码等价的控制字符
    {} 在定位行执行的命令组
    n 读取下一个输入行,用下一个命令处理新的行
    h 将模式缓冲区的文本复制到保持缓冲区
    H ...追加到保持缓冲区
    x 互换模式缓冲区和保持缓冲区内容
    g 将保持模式缓冲区的内容复制到模式缓冲区
    G ....追加到模式缓冲区

    示例

    测试文件内容:

        This is a Certificate Request file:
    
        It should be mailed to zawu@seu.edu.cn
    
        =====================================================
        Certificate Subject:
    
        /O=Grid/OU=GlobusTest/OU=simpleCA-seugridl.seu.edu.cn/OU=seu.edu.cn/CN=globus
    
        The above string is known as your user certificate subject, and t uniquely identifies theis user. $88
        To install this user certificate, please save this e-mail message into the following file.
    
        /home/alloy/linuxshell/CH02/usercert.pem
    

    sed -n: 不打印sed编辑对象的全部内容

    wsx@wsx-ubuntu:~/桌面$ sed -n '1p' input
        This is a Certificate Request file:
    
    wsx@wsx-ubuntu:~/桌面$ sed '1p' input
        This is a Certificate Request file:
        This is a Certificate Request file:
    
        It should be mailed to zawu@seu.edu.cn
    
        =====================================================
        Certificate Subject:
    
        /O=Grid/OU=GlobusTest/OU=simpleCA-seugridl.seu.edu.cn/OU=seu.edu.cn/CN=globus
    
        The above string is known as your user certificate subject, and t uniquely identifies theis user. $88
        To install this user certificate, please save this e-mail message into the following file.
    
        /home/alloy/linuxshell/CH02/usercert.pem
    
    

    利用sed命令打印范围行:

    wsx@wsx-ubuntu:~/桌面$ sed -n '3,6p' input 
        It should be mailed to zawu@seu.edu.cn
    
        =====================================================
        Certificate Subject:
    
    

    sed -e: sed传递多个编辑命令时使用

    wsx@wsx-ubuntu:~/桌面$ sed -n '/Certificate/=' input 
    1
    6
    
    wsx@wsx-ubuntu:~/桌面$ sed -n -e '/Certificate/p' input  -e '/Certificate/=' input
        This is a Certificate Request file:
    1
        Certificate Subject:
    6
    
    
    

    sed -f:调用sed脚本文件时才起作用

    wsx@wsx-ubuntu:~/桌面$ sed '/file:/a\We append a new line.' input 
        This is a Certificate Request file:
    We append a new line.
    
        It should be mailed to zawu@seu.edu.cn
    
        =====================================================
        Certificate Subject:
    
        /O=Grid/OU=GlobusTest/OU=simpleCA-seugridl.seu.edu.cn/OU=seu.edu.cn/CN=globus
    
        The above string is known as your user certificate subject, and t uniquely identifies theis user. $88
        To install this user certificate, please save this e-mail message into the following file.
    
        /home/alloy/linuxshell/CH02/usercert.pem
    
    

    脚本用法:

    #! /bin/sed -f 
    /file:/a\       #a\表示在此处添加文本
    
    # 添加文本
    We append a new line.\
    We append a another line.
    

    sed基本编辑命令可以放在单引号内,也可放在单引号外。

    sed文本定位的一组例子

    1. 匹配元字符,用转义符\进行屏蔽

      wsx@wsx-ubuntu:~/桌面$ sed -n '/\./p' input 
       It should be mailed to zawu@seu.edu.cn
       /O=Grid/OU=GlobusTest/OU=simpleCA-seugridl.seu.edu.cn/OU=seu.edu.cn/CN=globus
       The above string is known as your user certificate subject, and t uniquely identifies theis user. $88
       To install this user certificate, please save this e-mail message into the following file.
       /home/alloy/linuxshell/CH02/usercert.pem
      
      
    2. 使用元字符进行匹配

      $在sed命令中表示最后一行

      wsx@wsx-ubuntu:~/桌面$ sed -n '$p' input
       /home/alloy/linuxshell/CH02/usercert.pem
      
    3. !符号,打印不在2-10的行

      wsx@wsx-ubuntu:~/桌面$ sed -n '2,10!p' input 
       This is a Certificate Request file:
       To install this user certificate, please save this e-mail message into the following file.
      
       /home/alloy/linuxshell/CH02/usercert.pem
      
    4. 使用行号和关键字匹配限定行范围

      wsx@wsx-ubuntu:~/桌面$ sed -n '/seugrid/,$p' input 
       /O=Grid/OU=GlobusTest/OU=simpleCA-seugridl.seu.edu.cn/OU=seu.edu.cn/CN=globus
      
       The above string is known as your user certificate subject, and t uniquely identifies theis user. $88
       To install this user certificate, please save this e-mail message into the following file.
      
       /home/alloy/linuxshell/CH02/usercert.pem
      

    sed基本编辑命令的一组例子

    1. 插入文本:运行脚本,以输入文件名作为参数

      #!/bin/sed -f
      /file:/i\             # i\表示此处换行插入文本
      We insert a new line.
      
    2. 修改文本

      #!/bin/sed -f
      
      /file:/c\             #c\表示此处换行修改文本
      We modify this line      #修改文本内容
      
    3. 删除文本,符号是d,不带\,与其他命令有所区别,非常灵活。下面删除第一行和最后一行。

      wsx@wsx-ubuntu:~/桌面$ sed '1d' input
      
       It should be mailed to zawu@seu.edu.cn
      
       =====================================================
       Certificate Subject:
      
       /O=Grid/OU=GlobusTest/OU=simpleCA-seugridl.seu.edu.cn/OU=seu.edu.cn/CN=globus
      
       The above string is known as your user certificate subject, and t uniquely identifies theis user. $88
       To install this user certificate, please save this e-mail message into the following file.
      
       /home/alloy/linuxshell/CH02/usercert.pem
      wsx@wsx-ubuntu:~/桌面$ sed '$d' input
       This is a Certificate Request file:
      
       It should be mailed to zawu@seu.edu.cn
      
       =====================================================
       Certificate Subject:
      
       /O=Grid/OU=GlobusTest/OU=simpleCA-seugridl.seu.edu.cn/OU=seu.edu.cn/CN=globus
      
       The above string is known as your user certificate subject, and t uniquely identifies theis user. $88
       To install this user certificate, please save this e-mail message into the following file.
      
      
    4. 替换文本,格式s/被替换的字符串/新字符串/[替换选项]

      选项 意义
      g 全局匹配替换(替换所有的)
      p 与-n选项结合,只打印替换行
      w 文件名 表示将输出定向到一个文件
      sx@wsx-ubuntu:~/桌面$ sed 's/Certificate/CERTIFICATE/' input
       This is a CERTIFICATE Request file:
      
       It should be mailed to zawu@seu.edu.cn
      
       =====================================================
       CERTIFICATE Subject:
      
       /O=Grid/OU=GlobusTest/OU=simpleCA-seugridl.seu.edu.cn/OU=seu.edu.cn/CN=globus
      
       The above string is known as your user certificate subject, and t uniquely identifies theis user. $88
       To install this user certificate, please save this e-mail message into the following file.
      
       /home/alloy/linuxshell/CH02/usercert.pem
      wsx@wsx-ubuntu:~/桌面$ sed -n 's/Certificate/CERTIFICATE/p' input
       This is a CERTIFICATE Request file:
       CERTIFICATE Subject:
      
    5. 写入到一个新文件

      wsx@wsx-ubuntu:~/桌面$ sed -n 's/Certificate/CERTIFICATE/pg' input
       This is a CERTIFICATE Request file:
       CERTIFICATE Subject:
      wsx@wsx-ubuntu:~/桌面$ 
      wsx@wsx-ubuntu:~/桌面$ sed -n '1,5 w output' input
      wsx@wsx-ubuntu:~/桌面$ cat output 
       This is a Certificate Request file:
      
       It should be mailed to zawu@seu.edu.cn
      
       =====================================================
      
      
    6. 从文件中可读入文本,格式指定地址 r 文件名

    7. 退出命令:q

    8. 变换命令:sed命令的y表示字符变换(不等长时会报错)

      wsx@wsx-ubuntu:~/桌面$ sed 'y/fmj/FMJ/' input 
       This is a CertiFicate Request File:
      
       It should be Mailed to zawu@seu.edu.cn
      
       =====================================================
       CertiFicate SubJect:
      
       /O=Grid/OU=GlobusTest/OU=siMpleCA-seugridl.seu.edu.cn/OU=seu.edu.cn/CN=globus
      
       The above string is known as your user certiFicate subJect, and t uniquely identiFies theis user. $88
       To install this user certiFicate, please save this e-Mail Message into the Following File.
      
       /hoMe/alloy/linuxshell/CH02/usercert.peM
      
      
    9. 显示控制字符:控制字符就是非打印字符,如退格键、F1键等。使用sed l命令。

    10. 在命令行执行命令组,用{}符号,与-e选项功能类似。

      wsx@wsx-ubuntu:~/桌面$ sed -n '/Certificate/{p;=}' input
          This is a Certificate Request file:
      1
          Certificate Subject:
      6
      

    awk编程

    awk是三位前辈开发的编程语言,awk是三位创建者的首字母。基本语言与C类似。

    目前,使用的是gawk,Linux系统中/bin目录下有awkgawk两个命令,前者实际上是后者的链接。利用gawk语言可以实现数据查找、抽取文件中的数据、创建管道流命令等功能。

    我们可以简单地将awk编程模型分位三个阶段:

    • 读输入文件执行的执行代码段(由BEGIN关键字标识)
    • 读取输入文件时执行代码段
    • 读输入文件之后的执行代码段(由END关键字标识)

    调用方法分为两种:Sehll命令行方式;脚本执行。

    awk模式匹配

    任何awk语句都由模式和动作组成。模式是一组用于测试输入行是否需要执行动作的规则,动作是包含语句、函数和表达式的执行过程。awk支持所有的正则表达式元字符,以及?+两个扩展元字符。

    wsx@wsx-ubuntu:~/桌面$ awk '/^$/{print "This is a blank line."}' input
    This is a blank line.
    This is a blank line.
    This is a blank line.
    This is a blank line.
    This is a blank line.
    

    单引号中间为awk命令,由两部分组成,以“/”符号分隔,^$是模式,花括号部分是动作。该awk表示一旦读入的输入文件是空行,就打印后面的字符串This is a blank line

    使用脚本(将命令输入一个文件中):

    wsx@wsx-ubuntu:~/桌面$ awk -f src.awk input
    This is a blank line.
    This is a blank line.
    This is a blank line.
    This is a blank line.
    This is a blank line.
    

    内容不止这些,我们先谈谈其他概念。

    记录和域

    awk认为输入文件是结构化的,awk将每个输入文件行定义为记录,行中的每一个字符串定义为域,域之间用空格、TAB键或其他符号进行分隔,分隔域的符号就叫分隔符。(这个结构化概念需要理解,很多命令和编程中都有涉及)

    wsx@wsx-ubuntu:~/桌面$ awk '{print $2,$1,$4,$3}' sturecord 
    Hao Li 025------------ njue
    Ju Zhang 025---------- nju
    Bin Wang 025------ seu
    wsx@wsx-ubuntu:~/桌面$ awk '{print $0}' sturecord 
    Li Hao  njue 025------------ 
    Zhang Ju    nju 025---------- 
    Wang Bin    seu 025------
    

    可以通过对域的操作对文本进行重新排列,也可以用print $0输入所有域。

    wsx@wsx-ubuntu:~/桌面$ awk 'BEGIN {one=1;two=2}{print $(one+two)}' sturecord 
    njue
    nju
    seu
    

    BEGIN字段中定义onetwo两个变量并赋值。

    -F选项用来改变分隔符,例如只以'\t'为分隔符。

    wsx@wsx-ubuntu:~/桌面$ awk -F'\t' '{print $2}' sturecord 
    025------------ 
    025---------- 
    025------
    

    注意-F-f的区别。

    awk还提供了另一种更方便的方法改变分隔符。

    wsx@wsx-ubuntu:~/桌面$ cat sturecord 
    Li Hao,njue,025------------ 
    Zhang Ju,nju,025---------- 
    Wang Bin,seu,025------
    wsx@wsx-ubuntu:~/桌面$ awk 'BEGIN {FS=","}{print $1, $3}' sturecord 
    Li Hao 025------------ 
    Zhang Ju 025---------- 
    Wang Bin 025------
    

    关系和布尔运算符

    awk定义了一组关系运算符用于awk模式匹配。如下表

    运算符 意义
    < 小于
    > 大于
    <= 小于或等于
    >= 大于或等于
    == 等于
    != 不等于
    ~ 匹配正则表达式
    !~ 不匹配正则表达式

    用/etc/passwd文件做个例子

    # 第1域匹配root
    wsx@wsx-ubuntu:~/桌面$ awk 'BEGIN {FS=":"} $1~/root/' /etc/passwd
    # 全部域匹配root
    root:x:0:0:root:/root:/bin/bash
    wsx@wsx-ubuntu:~/桌面$ awk 'BEGIN {FS=":"} $0~/root/' /etc/passwd
    root:x:0:0:root:/root:/bin/bash
    # 全部域不匹配nologin
    wsx@wsx-ubuntu:~/桌面$ awk 'BEGIN {FS=":"} $0!~/nologin/' /etc/passwd
    root:x:0:0:root:/root:/bin/bash
    sync:x:4:65534:sync:/bin:/bin/sync
    systemd-timesync:x:100:102:systemd Time Synchronization,,,:/run/systemd:/bin/false
    systemd-network:x:101:103:systemd Network Management,,,:/run/systemd/netif:/bin/false
    systemd-resolve:x:102:104:systemd Resolver,,,:/run/systemd/resolve:/bin/false
    systemd-bus-proxy:x:103:105:systemd Bus Proxy,,,:/run/systemd:/bin/false
    syslog:x:104:108::/home/syslog:/bin/false
    _apt:x:105:65534::/nonexistent:/bin/false
    messagebus:x:106:110::/var/run/dbus:/bin/false
    uuidd:x:107:111::/run/uuidd:/bin/false
    lightdm:x:108:114:Light Display Manager:/var/lib/lightdm:/bin
    

    awk条件语句与C类似,有if语句,if/else语句以及if/else else语句三种。

    下面是支持的布尔运算符

    运算符 意义
    || 逻辑或
    && 逻辑与
    ! 逻辑非
    # 多条件精确匹配
    wsx@wsx-ubuntu:~/桌面$ awk 'BEGIN {FS=":"} {if($3==10||$4==10) print $0}' /etc/passwd
    # 多条件模糊匹配
    uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
    wsx@wsx-ubuntu:~/桌面$ awk 'BEGIN {FS=":"} {if($3~10||$4~10) print $0}' /etc/passwd
    uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
    systemd-timesync:x:100:102:systemd Time Synchronization,,,:/run/systemd:/bin/false
    systemd-network:x:101:103:systemd Network Management,,,:/run/systemd/netif:/bin/false
    systemd-resolve:x:102:104:systemd Resolver,,,:/run/systemd/resolve:/bin/false
    systemd-bus-proxy:x:103:105:systemd Bus Proxy,,,:/run/systemd:/bin/false
    syslog:x:104:108::/home/syslog:/bin/false
    _apt:x:105:65534::/nonexistent:/bin/false
    messagebus:x:106:110::/var/run/dbus:/bin/false
    uuidd:x:107:111::/run/uuidd:/bin/false
    lightdm:x:108:114:Light Display Manager:/var/lib/lightdm:/bin/false
    whoopsie:x:109:116::/nonexistent:/bin/false
    avahi-autoipd:x:110:119:Avahi autoip daemon,,,:/var/lib/avahi-autoipd:/bin/false
    wsx:x:1000:1000:wsx,,,:/home/wsx:/bin/bash
    nx:x:123:1001::/var/NX/nx:/etc/NX/nxserver
    

    表达式

    一个awk表达式可以由数值、字符常量、变量、操作符、函数和正则表达式自由组合而成。

    运算符 意义
    +
    -
    *
    /
    %
    ^或** 乘方
    ++x 在返回x之前,x变量加1
    x++ 在返回x之后,x变量加1
    wsx@wsx-ubuntu:~/桌面$ awk '/^$/{print x+=1}' input
    1
    2
    3
    4
    5
    

    系统变量

    awk定义了很多内建变量用于设置环境信息,我们称为系统变量。分为两种:一种用于改变awk的默认值,例如域分隔符;第二种用于定义系统值,在处理文本时可以读取这些系统值。

    变量名 意义
    $n 当前记录的第n个域,域用FS分隔
    $0 记录的所有域
    ARGC 命令行参数的数量
    ARGIND 命令行中当前文件的位置(从0开始标号)
    ARGV 命令行参数的数组
    CONVFMT 数字转换格式
    ENVIRON 环境变量关联数组
    ERRNO 最后一个系统错误的描述
    FIELDWIDTHS 字段宽度列表,以空格键分隔
    FILENAME 当前文件名
    FNR 浏览文件的记录数
    FS 字段分隔符,默认是空格键
    IGNORECASE 布尔变量,如果为真,则进行忽略大小写的匹配
    NF 当前记录中的域数量
    NR 当前记录数
    OFMT 数字的输出格式
    OFS 输出域分隔符,默认是空格键
    ORS 输出记录分隔符,默认是换行符
    RLENGTH 由match函数所匹配的字符串长度
    RS 记录分隔符,默认是空格键
    RSTART 由match函数所匹配的字符串的第1个位置
    SUBSEP 数组下标分隔符,默认值是\034

    格式化输出

    awk借鉴C语言的语法,定义了printf输出语句。基本语法如下:

    printf(格式控制符, 参数)

    格式控制符分为修饰符和格式符两种,如下:

    修饰符 意义
    - 左对齐
    width 域的步长
    .prec 小数点右边的位数
    运算符 意义
    %c ASCII字符
    %d 整型数
    %e 浮点数,科学计数法
    %f 浮点数
    %o 八进制数
    %s 字符串
    %x 十六进制数

    内置字符串函数

    awk提供了强大的内置字符串函数,用于实现文本的字符串替换、查找以及分隔等功能,下表列出:

    函数名 意义
    gsub(r,s) 在输入文件中用s替换r
    gsub(r,s,t) 在t中用s替换r
    index(s,t) 返回s中字符串第一个t的位置
    length(s) 返回s的长度
    match(s,t) 测试s是否包含匹配t的字符串
    split(r,s,t) 在t上将r分为序列s
    sub(r,s,t) 将t中第1次出现的r替换为s
    substr(r,s) 返回字符串r中从s开始的后缀部分
    substr(r,s,t) 返回字符串r中从s开始长度为t的后缀部分

    向awk脚本传递参数

    awk脚本内的变量可以在命令行中进行赋值,实现向awk脚本传递参数,变量赋值放在脚本之后、输入文件之前,格式为:

    awk脚本 parameter=value 输入文件

    条件语句和循环语句

    看起来基本和C一样,框架如下——

    if (条件表达式)
        动作1
    [else
        动作2]
    
    while(条件表达式)
        动作
    
    do
        动作
    while(条件表达式)
    
    for(设置计数器初值; 测试计数器; 计数器变化)
        动作
    

    数组

    数组是存储一系列值的变量,可通过索引来访问数组的值,索引需要用中括号括起,数组的基本格式为:

    array[index]=value

    形式和C一样,但awk数组无需定义数组类型和大小,可以直接赋值后使用。一般用在for循环中

    for (variable in array)
        do somethng with array[variable]
    

    更多操作可以查看:http://man.linuxde.net/awk

    参考:Linux Shell编程——从初学到精通(第2版)

    相关文章

      网友评论

      本文标题:【shell笔记>命令】grep,sed,awk

      本文链接:https://www.haomeiwen.com/subject/dqtjattx.html