zoukankan      html  css  js  c++  java
  • Linux高级文本处理命令

    cut

    一、cut命令

      功能:cut命令可以从一个文本文件/文本流中提取文本列

      语法:

      cut -d '分割字符' -f fields  ##用于有特定分割字符

      cut -c 字符区间  ##用于排列整齐的信息

      选项与参数:

    • -d:后面接分隔字符。与 -f 一起使用;
    • -f:依据 -d 的分隔字符将一段信息分割成为数段,用 -f 取出第几段的意思
    • -c:以字符(charaters)的单位取出固定字符区间

    sed

    简介:行编辑器

    解决的问题:

    1. 处理文本文件
    2. 分析日志文件
    3. 修改配置文件

    sed 的处理流程

      读入一行到模式空间,理解为一个临时缓冲区

      注意:sed 本身就有输出到屏幕这一步

    sed的原则

    1. sed 一次只处理一行内容
    2. sed 默认不可以改变文件内容(除非重定向或者用 -i 参数)
    3. sed 可以对所有行进行操作,也可以根据正则选定行

    sed 的格式

    1、命令行格式

      sed [options] 'command' file

      options: -e,-n,-i(optuions 为可选项)

      -e  # 执行多次 sed 命令

      -n  # 忽略默认输出

      -i   # 修改文件

      command:行定位/正则定位+ sed 命令(操作)

    2、脚本格式

      sed -f scriptfile file

    sed 命令

    我们复制一个文件,进行操作,内容如下:(nl 就是输出带行号, -b a 就是把空白行也带上行号)

     # nl -b a passwd 
    1
    root:x:0:0:root:/root:/bin/bash 2 bin:x:1:1:bin:/bin:/sbin/nologin 3 daemon:x:2:2:daemon:/sbin:/sbin/nologin 4 adm:x:3:4:adm:/var/adm:/sbin/nologin 5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin 6 sync:x:5:0:sync:/sbin:/bin/sync 7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown 8 9 halt:x:7:0:halt:/sbin:/sbin/halt 10 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin 11 uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin 12 operator:x:11:0:operator:/root:/sbin/nologin 13 games:x:12:100:games:/usr/games:/sbin/nologin 14 gopher:x:13:30:gopher:/var/gopher:/sbin/nologin 15 ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin 16 nobody:x:99:99:Nobody:/:/sbin/nologin 17 vcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologin 18 19 20 saslauth:x:499:76:Saslauthd user:/var/empty/saslauth:/sbin/nologin 21 postfix:x:89:89::/var/spool/postfix:/sbin/nologin 22 sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin 23 ntp:x:38:38::/etc/ntp:/sbin/nologin 24 tcpdump:x:72:72::/:/sbin/nologin 25 nscd:x:28:28:NSCD Daemon:/:/sbin/nologin 26 mysql:x:27:27:MySQL Server:/var/lib/mysql:/bin/bash 27 apache:x:48:48:Apache:/var/www:/sbin/nologin 28 dockerroot:x:498:497:Docker User:/var/lib/docker:/sbin/nologin

    1、p

      sed 'p' passwd  ## 打印出文件内容,但是每一行打印出了两行

      sed -n 'p' passwd  ## 忽略默认输出

    2、行定位

    定位一行

    x:行号

      sed -n '10p' passwd  ## 定位到第 10 行

      nl -b a passwd | sed -n '10p'  ## 定位到第 10 行

    /pattern/:正则

      sed -n '/mysql/p' passwd  ## 定位到含 mysql 的行

    定位几行

    x,y:行号

      nl -b a passwd | sed -n '10,20p'  ## 定位到第 10-20 行

    /pattern/,x:正则

      sed -n '/nobody/,/sshd/'  ## 定位到含有 nobody 的行到含有 sshd 的这一行

    x,y!:不选择这一行

      nl passwd | sed -n '10!p'  ## 不显示第 10 行的内容

      nl passwd | sed -n '10,20!p'  ## 不显示 10-20 行的内容

    间隔几行

    first ~ step(first:开始行,step:步进)

      nl -b a passwd | sed -n '1~2p'  ## 从第一行开始,每两行打印一次

    # sed -n '10p' passwd   ## 打印第 10 行
    mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
    
    # sed -n '/nobody/p' passwd   ## 打印包含 nobody 的行
    nobody:x:99:99:Nobody:/:/sbin/nologin
    
    # sed -n '6,10p' passwd   ## 打印 6-10 行(包括其中的空白行)
    sync:x:5:0:sync:/sbin:/bin/sync
    shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
    
    halt:x:7:0:halt:/sbin:/sbin/halt
    mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
    
    # sed -n '/nobody/,/sshd/p' passwd   ## 打印 nobody 那一行到 sshd 那一行
    nobody:x:99:99:Nobody:/:/sbin/nologin
    vcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologin
    
    
    saslauth:x:499:76:Saslauthd user:/var/empty/saslauth:/sbin/nologin
    postfix:x:89:89::/var/spool/postfix:/sbin/nologin
    sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
    
    # sed -n '20,/sshd/p' passwd   ## 打印从 20 行到 sshd 这一行
    saslauth:x:499:76:Saslauthd user:/var/empty/saslauth:/sbin/nologin
    postfix:x:89:89::/var/spool/postfix:/sbin/nologin
    sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin

    # nl -b a passwd | sed -n '1~2p'  ## 从第 1 行开始,每 2 行打印一次
         1    root:x:0:0:root:/root:/bin/bash
         3    daemon:x:2:2:daemon:/sbin:/sbin/nologin
         5    lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
         7    shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
         9    halt:x:7:0:halt:/sbin:/sbin/halt
        11    uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
        13    games:x:12:100:games:/usr/games:/sbin/nologin
        15    ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
        17    vcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologin
        19    
        21    postfix:x:89:89::/var/spool/postfix:/sbin/nologin
        23    ntp:x:38:38::/etc/ntp:/sbin/nologin
        25    nscd:x:28:28:NSCD Daemon:/:/sbin/nologin
        27    apache:x:48:48:Apache:/var/www:/sbin/nologin

    3、行处理命令

    基本命令

      -a(新增行)/i(插入行)

    # nl -b a passwd | sed '3aganziwenganziwen'  ## 在第 3 行后面新增行,内容为 ganziwenganziwen
         1    root:x:0:0:root:/root:/bin/bash
         2    bin:x:1:1:bin:/bin:/sbin/nologin
         3    daemon:x:2:2:daemon:/sbin:/sbin/nologin
    ganziwenganziwen
         4    adm:x:3:4:adm:/var/adm:/sbin/nologin
         5    lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

    # nl -b a passwd | sed '3iganziwenganziwen'  ## 在第 3 行前面插入行,内容为 ganziwenganziwen
         1    root:x:0:0:root:/root:/bin/bash
         2    bin:x:1:1:bin:/bin:/sbin/nologin
    ganziwenganziwen
         3    daemon:x:2:2:daemon:/sbin:/sbin/nologin
         4    adm:x:3:4:adm:/var/adm:/sbin/nologin
         5    lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

    # nl -b a passwd | sed '3,5aganziwenganziwen'  ## 在第 3-5 行之间的每一行都新增 ganziwenganziwen
         1    root:x:0:0:root:/root:/bin/bash
         2    bin:x:1:1:bin:/bin:/sbin/nologin
         3    daemon:x:2:2:daemon:/sbin:/sbin/nologin
    ganziwenganziwen
         4    adm:x:3:4:adm:/var/adm:/sbin/nologin
    ganziwenganziwen
         5    lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
    ganziwenganziwen
         6    sync:x:5:0:sync:/sbin:/bin/sync
         7    shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

    # nl -b a passwd | sed '3,5iganziwenganziwen'  ## 在第 3-5 行之间的每一行都插入 ganziwenganziwen
         1    root:x:0:0:root:/root:/bin/bash
         2    bin:x:1:1:bin:/bin:/sbin/nologin
    ganziwenganziwen
         3    daemon:x:2:2:daemon:/sbin:/sbin/nologin
    ganziwenganziwen
         4    adm:x:3:4:adm:/var/adm:/sbin/nologin
    ganziwenganziwen
         5    lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
         6    sync:x:5:0:sync:/sbin:/bin/sync
         7    shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

      -c(替换行)

    # nl -b a passwd | sed '3c========='  ## 把第 3 行替换成 ========
         1    root:x:0:0:root:/root:/bin/bash
         2    bin:x:1:1:bin:/bin:/sbin/nologin
    =========
         4    adm:x:3:4:adm:/var/adm:/sbin/nologin
         5    lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

    # nl -b a passwd | sed '3,5c========='  ## 把第 3-5 行内所有的内容全部替换成 1 个 ==========
         1    root:x:0:0:root:/root:/bin/bash
         2    bin:x:1:1:bin:/bin:/sbin/nologin
    =========
         6    sync:x:5:0:sync:/sbin:/bin/sync
         7    shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
         8    
         9    halt:x:7:0:halt:/sbin:/sbin/halt

      -d(删除行)

    # nl -b a passwd | sed '3,5d'  ## 把 3-5 行全部删除
         1    root:x:0:0:root:/root:/bin/bash
         2    bin:x:1:1:bin:/bin:/sbin/nologin
         6    sync:x:5:0:sync:/sbin:/bin/sync
         7    shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

     

     练习1:修改配置文件

      在 /etc/profile 中添加环境变量

    这里,我只贴出环境变量文件的后几行,以供对比

       ……   
    85
    #python3.6 86 PATH=$PATH:$HOME/bin:/usr/local/python3/bin 87 export PATH

    要解决这个问题有俩难点:1、怎么定位最后一行($ 代表最后一行);2、添加用什么命令

    sed 命令如下:

    # sed '$a export GZW_HOME=XXX
    export PATH=$PATH:$GZW_HOME' profile  ## 里面加了 
     为换行符
    ……
    #python3.6
    PATH=$PATH:$HOME/bin:/usr/local/python3/bin
    export PATH
    export GZW_HOME=XXX
    export PATH=$PATH:$GZW_HOME

    这么写有个问题,就是假设我们前面要加 4 个空格,而我们是顶格写出来的,怎么办?

    解决办法:中间的我们可以加空格,但是第一行加不了空格,需要加一个

    # sed '$a    export GZW_HOME=XXX
        export PATH=$PATH:$GZW_HOME' profile 
    ……
    #python3.
    6 PATH=$PATH:$HOME/bin:/usr/local/python3/bin export PATH export GZW_HOME=XXX export PATH=$PATH:$GZW_HOME

    注意:这么写只是输出到屏幕的内容修改了,但是我们没有加 options ,所以默认是不会修改到文件内的,那么要直接修改呢?之前我们讲过,要么重定向 ,要么用 -i 参数

    # sed -i '$a    export GZW_HOME=XXX
        export PATH=$PATH:$GZW_HOME' profile
    
    # cat profile
    ……
    #python3.6
    PATH=$PATH:$HOME/bin:/usr/local/python3/bin
    export PATH
        export GZW_HOME=XXX
        export PATH=$PATH:$GZW_HOME

     而且,重定向有问题,如果我们直接 > 的话,那么会把文件清空了。我们得用 >> 追加写的方式,但是追加写又有个问题,那就是会把显示的全部追加进去,也就是说,配置文件有俩大段一样的,那么怎么弄呢?

    出现这个问题的原因就是因为会把默认输出的内容也追加进去我们加个 -n 参数就 ok

    # sed -n '$a    export GZW_HOME=XXX
        export PATH=$PATH:$GZW_HOME' profile >> profile

    练习2:删除空白行

      sed '/^$/d' file  ## ^ 代表开头,$ 代表结尾

    # sed '/^$/d' passwd

    练习3:服务器日志处理——服务器 log 中打印 error 信息

      sed -n '/Error/p' file ## 用正则匹配到 Error 信息

    # sed -n '/Error/p' catalina.out

    替换操作:s

    分隔符: /

    全局替换: g

    例如:

      sed 's/nologin/login' passwd  ## 将文件内每一行的第一个 nologin 替换成 login

      sed 's/:/%/g' passwd  ## 将文件内所有的 : 替换成 %

    # sed 's/nologin/login/' passwd
    ……
    bin:x:1:1:bin:/bin:/sbin/login
    daemon:x:2:2:daemon:/sbin:/sbin/login
    adm:x:3:4:adm:/var/adm:/sbin/login
    lp:x:4:7:lp:/var/spool/lpd:/sbin/login
    ……
    
    # sed 's/:/%/' passwd   ## 只有第一个 : 换成了 %
    root%x:0:0:root:/root:/bin/bash
    bin%x:1:1:bin:/bin:/sbin/nologin
    
    # sed 's/:/%/g' passwd   ## 加入 g ,则会全部替换
    root%x%0%0%root%/root%/bin/bash
    bin%x%1%1%bin%/bin%/sbin/nologin
    daemon%x%2%2%daemon%/sbin%/sbin/nologin

    练习:取出 ifconfig 命令内的 ip 地址

    分两步:1、先找到有 ip 的那一行,2、把那一行的除 ip 外的信息换成空字符串

    # ifconfig | sed -n '/inet/p'
              inet addr:172.17.42.1  Bcast:0.0.0.0  Mask:255.255.0.0
              inet addr:127.0.0.1  Mask:255.0.0.0

    # ifconfig | sed -n '/inet .* Bcast/p'  ## 正则里面再筛选 .* 代表中间还有内容,后面有 Bcast
              inet addr:172.17.42.1  Bcast:0.0.0.0  Mask:255.255.0.0

    # ifconfig | sed -n '/inet .* Bcast/p' | sed 's/inet.*r://'  ## 这里升级,把 ip 的前半拉替换成空字符(inet开头,r:结尾)
              172.17.42.1  Bcast:0.0.0.0  Mask:255.255.0.0

    # ifconfig | sed -n '/inet .* Bcast/p' | sed 's/inet.*r://' | sed 's/Bcast.*//'  ## 再把 Bcast 后面的全部替换成空字符
              172.17.42.1 

    # ifconfig | sed -n '/inet .* Bcast/p' | sed 's/s+inet.*r://' | sed 's/s+Bcast.*//'  ## 上述操作有空白出现,利用 s 代表空白 + 表一个以上符,但是 + 需要转译,所以为 s+
    172.17.42.1

     sed 高级操作

     {} :多个 sed 命令,用 ; 分开(实际操作上,{} 并不是必要的,加了没加还是有点区别)

      nl passwd | sed '{10,20;s/false/true/}'

    n: 读取下一个输入行(用下一个命令处理)

      nl passwd | sed '{n;p}'

      nl passwd | sed '{p;n}'

      nl passwd | sed '{p;n;n}'

      也可以用间隔行进行输出

    # sed '{1,3p;s/:/%/}' passwd 
    root:x:0:0:root:/root:/bin/bash
    root%x:0:0:root:/root:/bin/bash
    bin:x:1:1:bin:/bin:/sbin/nologin
    bin%x:1:1:bin:/bin:/sbin/nologin
    daemon:x:2:2:daemon:/sbin:/sbin/nologin
    daemon%x:2:2:daemon:/sbin:/sbin/nologin
    adm%x:3:4:adm:/var/adm:/sbin/nologin
    lp%x:4:7:lp:/var/spool/lpd:/sbin/nologin
    sync%x:5:0:sync:/sbin:/bin/sync
    shutdown%x:6:0:shutdown:/sbin:/sbin/shutdown
    ……
    
    # sed '{1,3d;s/:/%/}' passwd   ## 其实不加 {} 也可以
    adm%x:3:4:adm:/var/adm:/sbin/nologin
    lp%x:4:7:lp:/var/spool/lpd:/sbin/nologin
    sync%x:5:0:sync:/sbin:/bin/sync
    shutdown%x:6:0:shutdown:/sbin:/sbin/shutdown
    
    halt%x:7:0:halt:/sbin:/sbin/halt
    ……

      
    # nl -b a passwd | sed -n '{n;p}'  ## 第一行被越过了,不打印,所以打印 2,4,6……
         2    bin:x:1:1:bin:/bin:/sbin/nologin
         4    adm:x:3:4:adm:/var/adm:/sbin/nologin
         6    sync:x:5:0:sync:/sbin:/bin/sync
         8    
        10    mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
        12    operator:x:11:0:operator:/root:/sbin/nologin
        14    gopher:x:13:30:gopher:/var/gopher:/sbin/nologin
        16    nobody:x:99:99:Nobody:/:/sbin/nologin
        18    
        20    saslauth:x:499:76:Saslauthd user:/var/empty/saslauth:/sbin/nologin
        22    sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
        24    tcpdump:x:72:72::/:/sbin/nologin
        26    mysql:x:27:27:MySQL Server:/var/lib/mysql:/bin/bash
        28    dockerroot:x:498:497:Docker User:/var/lib/docker:/sbin/nologin

    # nl -b a passwd | sed -n '{n;n;p}'  ## 第一行以及第二行被跳过,所以打印 3,6,9……,跟 nl -b a passwd | sed -n '{3~3p}' 效果一样
         3    daemon:x:2:2:daemon:/sbin:/sbin/nologin
         6    sync:x:5:0:sync:/sbin:/bin/sync
         9    halt:x:7:0:halt:/sbin:/sbin/halt
        12    operator:x:11:0:operator:/root:/sbin/nologin
        15    ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
        18    
        21    postfix:x:89:89::/var/spool/postfix:/sbin/nologin
        24    tcpdump:x:72:72::/:/sbin/nologin
        27    apache:x:48:48:Apache:/var/www:/sbin/nologin


    &:替换固定的字符串,配合替换操作使用

    例如:将 passwd 中用户名后添加空格:

      sed 's/[a-z_-]+/& /' passwd

      [a-z_-]+代表每行开头的那堆字母,因为不止一个,所以要加 + ,而且要转译;

      &   注意,要加的内容在 & 符号后面,我这里是加了一个空格,可能不是特别明显。其实 & 就是匹配我们最前面的正则出来的东西,然后再在后面加空格

    # sed 's/[a-z_-]+/& /' passwd
    root :x:0:0:root:/root:/bin/bash
    bin :x:1:1:bin:/bin:/sbin/nologin
    daemon :x:2:2:daemon:/sbin:/sbin/nologin
    adm :x:3:4:adm:/var/adm:/sbin/nologin
    lp :x:4:7:lp:/var/spool/lpd:/sbin/nologin
    sync :x:5:0:sync:/sbin:/bin/sync
    shutdown :x:6:0:shutdown:/sbin:/sbin/shutdown

    将用户名的首字母转换成大写

    u l U L

    u l:对首字母转大写或小写

    U |L:对首一串字符转大写或小写

    例如:要求用户名首字母大写

      sed 's/[a-z_-]+/u&/' passwd

    # sed 's/[a-z_-]+/u&/' passwd
    Root:x:0:0:root:/root:/bin/bash
    Bin:x:1:1:bin:/bin:/sbin/nologin
    Daemon:x:2:2:daemon:/sbin:/sbin/nologin
    Adm:x:3:4:adm:/var/adm:/sbin/nologin
    Lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
    Sync:x:5:0:sync:/sbin:/bin/sync
    Shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

    练习:将文件夹下的 .txt 文件名转换为大写

      ls *.txt | sed 's/^w+/U&/'

    # ll
    total 4512
    -rw-r----- 1 root root 4600554 Feb  5 17:00 catalina.out
    -rw-r--r-- 1 root root       0 Feb  5 21:38 gzw.txt
    -rw-r--r-- 1 root root       0 Feb  5 21:38 Gzw.txt
    -rw-r----- 1 root root    5537 Jan 14 17:45 mysqld.log
    -rw-r--r-- 1 root root    1127 Feb  3 21:29 passwd
    -rw-r--r-- 1 root root    2067 Feb  4 09:54 profile
    
    # ls *.txt | sed 's/^w+/U&/'
    GZW.txt
    GZW.txt

    # ls | sed 's/.*/U&/'  ## 文件名包括格式全部换成大写
    CATALINA.OUT
    GZW.TXT
    GZW.TXT
    MYSQLD.LOG
    PASSWD
    PROFIL

    ():

    ( ):替换某种部分字符串 ( 1,2)

      s/w1w2w3/w2/

      s/w1(w2)(w3)/12/

    可能难以理解,我们搞个 txt 看一哈

    # cat gzw.txt 
    w1w2w3

    接下来演示一下:

    # cat gzw.txt | sed 's/w1(w2)(w3)/1,2/'  ## 可以把括号内的理解为把它暂时取出来,用 1 代替,第二个就用 2 代替,中间可以任意家字符,跟替换一样 
    w2,w3

    练习:获取 eth0 的 ip

    # ifconfig | sed -n '/inet.*B/p'  ## 首先,我们获取到 ip 的这一行
              inet addr:172.17.42.1  Bcast:0.0.0.0  Mask:255.255.0.0

    # ifconfig | sed -n '/inet.*B/p' | sed 's/inet.*r:([0-9.]+)+s+B/1/'  ## 后面那俩 ip 也跟着出来了
              172.17.42.1cast:0.0.0.0  Mask:255.255.0.0

    # ifconfig | sed -n '/inet.*B/p' | sed 's/inet.*r:([0-9.]+).+B.*$/1/'
              172.17.42.1

    练习:获取 passwd 中的用户名 uid ,gid,jid

      sed 's/(^[a-z_-]+):x:([0-9]+):([0-9]+):.*$/1,2,3/' passwd

    # sed 's/(^[a-z_-]+):x:([0-9]+):([0-9]+):.*$/1,2,3/' passwd
    root,0,0
    bin,1,1
    daemon,2,2
    adm,3,4
    lp,4,7
    sync,5,0
    shutdown,6,0

    r:读取指定文件插入到匹配行

      sed '1r 123.txt' abc.txt  ## 读文件不会更改文件内容

    w:复制匹配行拷贝指定文件里

      sed '1w 123.txt' abc.txt  ## 写操作会修改目标文件(将 abc.txt 的第一行写入到 123.txt 内,而且是覆盖写

    # cat 123.txt 
    123
    456
    789
    
    # cat abc.txt 
    abc
    def

    读:

    # sed '1r 123.txt' abc.txt  ## 读操作,不改变内容
    abc
    123
    456
    789
    def
    
    # cat 123.txt 
    123
    456
    789
    
    # cat abc.txt 
    abc
    def

     写:

    # sed '1w 123.txt' abc.txt  ## 将 abc.txt 的第一行写入到 123.txt 内
    abc
    def
    
    # cat 123.txt 
    abc
    
    # cat abc.txt 
    abc
    def

    q:退出 sed 使用 q 可以提前退出 sed

    # nl passwd | sed '10q'
         1    root:x:0:0:root:/root:/bin/bash
         2    bin:x:1:1:bin:/bin:/sbin/nologin
         3    daemon:x:2:2:daemon:/sbin:/sbin/nologin
         4    adm:x:3:4:adm:/var/adm:/sbin/nologin
         5    lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
         6    sync:x:5:0:sync:/sbin:/bin/sync
         7    shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
           
         8    halt:x:7:0:halt:/sbin:/sbin/halt
         9    mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
    
    # nl passwd | sed '/nologin/q'
         1    root:x:0:0:root:/root:/bin/bash
         2    bin:x:1:1:bin:/bin:/sbin/nologin

    -e:执行多次 sed 命令

    # nl -b a passwd | sed -e '10,20d' -e 's/:/%/g'
         1    root%x%0%0%root%/root%/bin/bash
         2    bin%x%1%1%bin%/bin%/sbin/nologin
         3    daemon%x%2%2%daemon%/sbin%/sbin/nologin
         4    adm%x%3%4%adm%/var/adm%/sbin/nologin
         5    lp%x%4%7%lp%/var/spool/lpd%/sbin/nologin
         6    sync%x%5%0%sync%/sbin%/bin/sync
         7    shutdown%x%6%0%shutdown%/sbin%/sbin/shutdown
         8    
         9    halt%x%7%0%halt%/sbin%/sbin/halt
        21    postfix%x%89%89%%/var/spool/postfix%/sbin/nologin
        22    sshd%x%74%74%Privilege-separated SSH%/var/empty/sshd%/sbin/nologin
        23    ntp%x%38%38%%/etc/ntp%/sbin/nologin
        24    tcpdump%x%72%72%%/%/sbin/nologin
        25    nscd%x%28%28%NSCD Daemon%/%/sbin/nologin
        26    mysql%x%27%27%MySQL Server%/var/lib/mysql%/bin/bash
        27    apache%x%48%48%Apache%/var/www%/sbin/nologin
        28    dockerroot%x%498%497%Docker User%/var/lib/docker%/sbin/nologin

    小技巧:如果在 sed 命令的正则表达式内,要使用我们的系统变量怎么办呢?两个方式

    1.sed命令使用双引号的情况下,使用$var直接引用

    $ echo|sed "s/^/$RANDOM.rmvb_/g"
    29328.rmvb_

    # 上面例子引用了一个环境变量$RANDOM的值

    2.sed命令使用单引号的情况下,使用'"$var"'引用,单引号里面加双引号,全为因为形式的引号

    类似,我们可以看到

    $ echo|sed 's/^/'"$RANDOM"'.rmvb_/g'
    31338.rmvb_

    面试题:

    1、修改某个目录下所有包含 aaa 文件的文件名,将 aaa 改成 AAA,目录结构树如下:

    # tree
    .
    ├── aaa.txt
    ├── aba
    │   ├── aaaA.txt
    │   ├── aaa.txt
    │   ├── Abaaa.txt
    │   └── ABA.txt
    ├── Abaaa.txt
    └── BBB
        ├── aaa.txt
        └── ABAB.txt

    写法:

    # find . -name '*aaa*' -exec rename aaa AAA {} ;
    # tree
    .
    ├── AAA.txt
    ├── aba
    │   ├── AAAA.txt
    │   ├── AAA.txt
    │   ├── AbAAA.txt
    │   └── ABA.txt
    ├── AbAAA.txt
    └── BBB
        ├── AAA.txt
        └── ABAB.txt

    1、修改某个目录下所有文件中包含 aaa,将文件内的 aaa 改成 AAA

    步骤:首先把把包含 aaa 的这些文件给找出来,其次再把 aaa 改成 AAA

    # grep aaa abc.txt   ## 这行命令的意思是,在 abc.txt 内找出有 aaa 的行
    aaa
    aaaBB

    # grep aaa -rl .  ## 代表递归,在当前目录下找出所有含有 aaa 的文件
    ./abc.txt
    ./qwe.txt
    ./456/lala.txt

    # sed 's/aaa/AAA/g' `grep aaa -rl .`  ## 这里注意要加全局 g ,不加的话,假设有个 aaaaaa ,那么只会替换前面的 aaa
    AAA
    AAA
    AAABB
    aaAa
    gzw
    a
    aa
    AAaaA
    1234
    qwe
    a
    AAA
    AAA
    A
    s
    e
    AAAA
    aa
    A
    aaA
    AAA
    aAaa
    AAaaAaAAAA

    # sed -i 's/aaa/AAA/g' `grep aaa -rl .`  ## 真正要修改要加 -i 参数

    awk

    简介:文本处理工具

    解决的问题:

    1. 一堆文本要分析
    2. 一堆数据要处理
    3. 分析服务器日志

    同样的,准备一个 passwd 文件

    # nl -b a passwd 
         1    root:x:0:0:root:/root:/bin/bash
         2    bin:x:1:1:bin:/bin:/sbin/nologin
         3    daemon:x:2:2:daemon:/sbin:/sbin/nologin
         4    adm:x:3:4:adm:/var/adm:/sbin/nologin
         5    lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
         6    sync:x:5:0:sync:/sbin:/bin/sync
         7    shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
         8    
         9    halt:x:7:0:halt:/sbin:/sbin/halt
        10    mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
        11    uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
        12    operator:x:11:0:operator:/root:/sbin/nologin
        13    games:x:12:100:games:/usr/games:/sbin/nologin
        14    gopher:x:13:30:gopher:/var/gopher:/sbin/nologin
        15    ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
        16    nobody:x:99:99:Nobody:/:/sbin/nologin
        17    vcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologin
        18    
        19    
        20    saslauth:x:499:76:Saslauthd user:/var/empty/saslauth:/sbin/nologin
        21    postfix:x:89:89::/var/spool/postfix:/sbin/nologin
        22    sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
        23    ntp:x:38:38::/etc/ntp:/sbin/nologin
        24    tcpdump:x:72:72::/:/sbin/nologin
        25    nscd:x:28:28:NSCD Daemon:/:/sbin/nologin
        26    mysql:x:27:27:MySQL Server:/var/lib/mysql:/bin/bash
        27    apache:x:48:48:Apache:/var/www:/sbin/nologin
        28    dockerroot:x:498:497:Docker User:/var/lib/docker:/sbin/nologin

     内置参数

    $0:表示整个当前行

    $1:每行第一个字段

    $2:每行第二个字段

    $n:每行第 n 个字段

    awk 的参数:分隔符

      -F separator  设定分隔符(默认为空格)

    # awk -F ':' '{print $1}' passwd   ## 以 : 为分隔符,打印第一列
    root
    bin
    daemon
    adm
    lp
    sync
    shutdown

    打印多个字段

    # awk -F ':' '{print $1,$3}' passwd 
    root 0
    bin 1
    daemon 2
    adm 3
    lp 4
    sync 5
    shutdown 6
    
    # awk -F ':' '{print $1"	"$3}' passwd 
    root    0
    bin    1
    daemon    2
    adm    3
    lp    4
    sync    5
    shutdown    6
    
    # awk -F ':' '{print $1"userid:"$3}' passwd 
    rootuserid:0
    binuserid:1
    daemonuserid:2
    admuserid:3
    lpuserid:4
    syncuserid:5
    shutdownuserid:6
    
    # awk -F ':' '{printf("Username:%s	Uid=%s
    ",$1,$3)}' passwd   ## 可以用 printf 函数形式输出
    Username:root    Uid=0
    Username:bin    Uid=1
    Username:daemon    Uid=2
    Username:adm    Uid=3
    Username:lp    Uid=4
    Username:sync    Uid=5
    Username:shutdown    Uid=6

    # awk -F ':' '{print "Username:"$1" Uid="$3}' passwd   ## 和上述效果一致
    Username:root    Uid=0
    Username:bin    Uid=1
    Username:daemon    Uid=2
    Username:adm    Uid=3
    Username:lp    Uid=4
    Username:sync    Uid=5

    NR:每行的行号

    NF:字段数量(相当于列,一行有多少个列)

    FILENAME:正在处理的文件名

    # awk -F ':' '{print NR,NF,FILENAME}' passwd   ## 第一行 7 列,文件名为 passwd
    1 7 passwd
    2 7 passwd
    3 7 passwd
    4 7 passwd
    5 7 passwd
    6 7 passwd

    练习:显示 /etc/passwd 每行的行号,每行的列数对应的用户名

    # awk -F ':' '{print "行号:" NR,"列数:"NF,"文件名:"$1}' passwd 
    行号:1 列数:7 文件名:root
    行号:2 列数:7 文件名:bin
    行号:3 列数:7 文件名:daemon
    行号:4 列数:7 文件名:adm
    行号:5 列数:7 文件名:lp
    行号:6 列数:7 文件名:sync
    行号:7 列数:7 文件名:shutdown


    # awk -F ':' '{printf("行号:%s列数:%s用户名:%s ",NR,NF,$1)}' passwd
    行号:1列数:7用户名:root
    行号:2列数:7用户名:bin
    行号:3列数:7用户名:daemon
    行号:4列数:7用户名:adm
    行号:5列数:7用户名:lp
    行号:6列数:7用户名:sync
    行号:7列数:7用户名:shutdown

    练习:显示 /etc/passwd 中用户 ID > 100 的行号以及用户名

    # awk -F ':' '{if ($3>100) print $1,$3}' passwd 
    saslauth 499
    dockerroot 498

    练习:在服务器的 apache 日志中找出 ip: 139.162.88.63 的访问日期

    日志的格式如下:

    139.162.88.63 - - [06/Feb/2019:17:03:23 +0800] "GET http://clientapi.ipip.net/echo.php?info=1234567890 HTTP/1.1" 404 290 "-" "Go-http-client/1.1"
    149.34.44.174 - - [06/Feb/2019:20:27:59 +0800] "GET / HTTP/1.1" 403 4961 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36"

    有两种方式:

    # sed -n '/139.162.88.63/p' access_log | awk '{print $1"	"substr($4,2)}'  ## 利用sed 找出行再处理;substr是截取字符串函数,不用的话,从 1 开始,不用的话,会有 [ 出现
    139.162.88.63    13/Jan/2019:17:21:22
    139.162.88.63    14/Jan/2019:18:56:59
    139.162.88.63    15/Jan/2019:19:43:35
    139.162.88.63    17/Jan/2019:19:12:26
    139.162.88.63    20/Jan/2019:19:59:47
    139.162.88.63    22/Jan/2019:17:16:44
    139.162.88.63    24/Jan/2019:21:32:20
    139.162.88.63    26/Jan/2019:23:09:01
    139.162.88.63    28/Jan/2019:19:02:10
    139.162.88.63    29/Jan/2019:17:34:58
    139.162.88.63    30/Jan/2019:18:00:42
    139.162.88.63    31/Jan/2019:20:00:52
    139.162.88.63    01/Feb/2019:20:42:48
    139.162.88.63    03/Feb/2019:17:50:28
    139.162.88.63    04/Feb/2019:19:48:18
    139.162.88.63    05/Feb/2019:21:04:14
    139.162.88.63    06/Feb/2019:17:03:23
    
    # awk '/139.162.88.63/{print $1"	"substr($4,2)}' access_log   ## 直接先用正则匹配出行
    139.162.88.63 13/Jan/2019:17:21:22 139.162.88.63 14/Jan/2019:18:56:59 139.162.88.63 15/Jan/2019:19:43:35 139.162.88.63 17/Jan/2019:19:12:26 139.162.88.63 20/Jan/2019:19:59:47 139.162.88.63 22/Jan/2019:17:16:44 139.162.88.63 24/Jan/2019:21:32:20 139.162.88.63 26/Jan/2019:23:09:01 139.162.88.63 28/Jan/2019:19:02:10 139.162.88.63 29/Jan/2019:17:34:58 139.162.88.63 30/Jan/2019:18:00:42 139.162.88.63 31/Jan/2019:20:00:52 139.162.88.63 01/Feb/2019:20:42:48 139.162.88.63 03/Feb/2019:17:50:28 139.162.88.63 04/Feb/2019:19:48:18 139.162.88.63 05/Feb/2019:21:04:14 139.162.88.63 06/Feb/2019:17:03:23

    逻辑判断式

    ~,!~ :匹配正则表达式

    ==,!=,<,> :判断逻辑表达式

    # awk -F ':' '$1~/^m.*/{print $1}' passwd   ## 以 m 开头的用户名
    mail
    mysql
    
    # awk -F ':' '$1!~/^m.*/{print $1}' passwd   ## 不以 m 开头的用户名
    root
    bin
    daemon
    adm
    lp
    sync
    shutdown

    # awk -F ':' '$3>100{print $1" "$3}' passwd
    saslauth    499
    dockerroot    498

    扩展格式

    command 扩展

    BEGIN{print "start"}pattern{awk 命令}END{print "END"}  ## 最开始先执行 BEGIN 后面的花括弧内容,再执行 awk 内的,最后再执行 END 花括弧内的

    练习:制表显示 /etc/passwd 每行的行号,每行的列数,对应的用户名

    # awk -F ':' 'BEGIN{print"User	Line	Col"}{print $1"	"NR"	"NF}END{"===="FILENAME"===="}' passwd 
    User    Line    Col
    root    1    7
    bin    2    7
    daemon    3    7
    adm    4    7
    lp    5    7
    sync    6    7
    ====passwd====

    练习:统计当前文件夹下的文件/文件夹占用的大小

    # ll
    total 513984
    -rw-r--r-- 1 root root    137514 Jan 14 17:51 1.log
    -rw-r--r-- 1 root root    177462 Jan 26 15:34 2.log
    -rw-r--r-- 1 root root    165223 Jan 26 15:46 3.log
    -rw-r--r-- 1 root root    273507 Jan 26 14:32 5.log
    -rw------- 1 root root 525542481 Feb  3 16:12 heap.bin
    drwxr-xr-x 2 root root      4096 Jan 26 16:02 scripts
    drwxr-xr-x 2 root root      4096 Feb  6 20:41 test
    
    # ll | awk 'BEGIN{count==0}{count+=$5}END{print count}'
    526304379

    # ll | awk 'BEGIN{count==0}{count+=$5}END{print count/1024/1024 "Mb"}'
    501.923Mb

    练习:统计显示 /etc/passwd 的账户总人数

    # awk -F ':' 'BEGIN{count==0}{count++}END{print count}' passwd  ## 每行其实就是个用户,但是这样写其实是把空行也计算进去了
    28

    # awk -F ':' 'BEGIN{count==0}$1!~/^$/{count++}END{print count}' passwd  ## 用正则排除空行
    25

    练习:统计显示 /etc/passwd 中 uid > 100 的用户名

    # awk -F ':' 'BEGIN{count==0}$3>100{user[count++]=$1}END{for(i=0;i<count;i++) print i,user[i]}' passwd 
    0 saslauth
    1 dockerroot

    练习:统计 access_log 日志中每个 ip 出现的次数

    # awk '{arr[$1]++}END{for(key in arr) print key,arr[key]}' access_log 
    39.104.135.252 1
    155.138.161.210 1
    64.68.233.90 1
    171.117.239.207 1
    36.78.107.210 1
    177.188.145.39 1
    177.84.43.202 1
    106.15.176.145 1
    103.110.164.134 1
    36.67.146.11 1
    94.241.165.85 1
    37.115.184.19 9
    139.224.15.159 1
    198.20.87.98 5
    103.204.166.138 1
    101.132.97.6 1
    106.14.168.238 3

    awk vs sed

    awk 和 sed 都可以处理文本

    awk 侧重于复杂逻辑处理

    sed 侧重于正则处理

    awk 和 sed 可以共同使用(统计上,awk 占点优势;sed 在修改文件上占优势)

  • 相关阅读:
    网络拓扑
    OSI 7层模型和TCP/IP 4层模型
    第一范式 第二范式 第三范式 BC范式 第四范式
    医院 信息科
    李纳斯•托瓦兹
    所谓绅士,就是做自己该做之事,而不是想做之事。
    活着
    开头词
    人际题目
    人际关系
  • 原文地址:https://www.cnblogs.com/xiaowenshu/p/10085363.html
Copyright © 2011-2022 走看看