zoukankan      html  css  js  c++  java
  • 9 文本处理工具

    9 文本处理工具

    1 文本处理工具介绍

    Linux上文本处理三剑客:

    • grep,egrep,fgrep :文本过滤工具(以模式:pattern 进行过滤)
      • grep:支持基本正则表达式,-E 选项可以支持扩展正则表达式,-F 选项支持 fgrep
      • egrep:扩展正则表达式,-G 选项可以支持基本正则表达式,-F 选项支持 fgrep
      • fgrep:不支持正则表达式
    • sed:stream editor,流编辑;文本编辑工具
    • awk:Linux上的实现为gawk,文本报告生成器(格式化文本)

    2 grep

    2.1 grep

    2.1.1 grep 简介

    grep:Global search REgular expression and Print out the line

    作用:文本搜索工具,根据用户指定的模式对目标文本逐行进行匹配检查,打印匹配到的行

    模式:由正则表达式元字符及文本字符所编写出的过滤条件

    正则表达式相关内容可参考博文:https://www.cnblogs.com/ckh2014/p/14100791.html

    2.1.1 grep 使用格式

    grep [OPTIONS] PATTERN [FILE...]

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

    常用选项:

    • --color=auto :对匹配到的文本着色后高亮显示
    • -i :ignorecase,忽略字符大小写
    • -o :仅显示匹配到的字符串本身
    • -v,--invert-match :显示不能够被pattern匹配到的行
    • -E :支持使用扩展的正则表达式元字符
    • -q,--quiet,--slient :静默模式,即不输出任何信息
    • -A #:after,后#行
    • -B #:before,前#行
    • -C #:context,前后各#行
    2.1.2 grep 示例

    1、显示/etc/passwd文件中不以/bin/bash结尾的行

    [root@node2 ~]# grep -v /bin/bash$ /etc/passwd

    2、找出/etc/passwd文件中两位数或三位数

    [root@node2 ~]# grep "\<[0-9]\{2,3\}\>" /etc/passwd

    3、找出/etc/rc.d/rc.sysinit或/etc/grub2.cfg文件中,以至少一个空白字符开头,且后面非空白字符的行

    [root@node2 ~]# grep "^[[:space:]]\+[^[:space:]]" /etc/grub2.cfg

    4、找出"netstat -atn"命令的结果中以"LISTEN"后跟0、1或多个空白字符结尾的行

    [root@node2 ~]# netstat -atn | grep "LISTEN[[:space:]]*$"

    2.2 egrep

    2.2.1 egrep 简介

    egrep 支持扩展的正则表达式实现类似于grep文本过滤功能;grep -E

    2.2.2 egrep 使用格式

    egrep [OPTIONS] PATTERN [FILE...]

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

    常用选项:

    • --color=auto :对匹配到的文本着色后高亮显示
    • -i :ignorecase,忽略字符大小写
    • -o :仅显示匹配到的字符串本身
    • -v,--invert-match :显示不能够被pattern匹配到的行
    • -G:支持基本正则表达式
    • -q,--quiet,--slient :静默模式,即不输出任何信息
    • -A #:after,后#行
    • -B #:before,前#行
    • -C #:context,前后各#行
    2.2.3 egrep示例

    练习1:

    1、显示/etc/passwd文件中不以/bin/bash结尾的行

    [root@node2 ~]# egrep -v "/bin/bash$" /etc/passwd

    2、找出/etc/passwd文件中两位数或三位数

    [root@node2 ~]# egrep "[0-9]{2,3}" /etc/passwd

    3、找出/etc/rc.d/rc.sysinit或/etc/grub2.cfg文件中,以至少一个空白字符开头,且后面非空白字符的行

    [root@node2 ~]# egrep "^[[:space:]]+[^[:space:]]" /etc/grub2.cfg

    4、找出"netstat -atn"命令的结果中以"LISTEN"后跟0、1或多个空白字符结尾的行

    [root@node2 ~]# netstat -atn | egrep "LISTEN[[:space:]]*$"

    练习2:

    1、找出 /proc/meminfo 文件中,所有以大写或小写S开头的行;至少有三种实现方式;

    [root@node2 ~]# grep -i "^[Ss]" /proc/meminfo

    [root@node2 ~]# grep -i ^s /procmeminfo

    [root@node2 ~]# egrep -i ^S /proc/meminfo

    [root@node2 ~]# grep -E "^(s|S)" /proc/meminfo

    2、显示当前系统上root、centos或user1用户的相关信息;

    [root@node2 ~]# egrep "^(root|centos|user1)\>" /etc/passwd

    3、找出 /etc/rc.d/init.d/functions 文件中某单词后面跟一个小括号的行;

    [root@node2 ~]# egrep "^[_[:alnum:]]+\(\)" /etc/rc.d/init.d/functions

    4、使用echo命令输出一绝对路径,使用egrep取出基名;

    [root@node2 ~]# echo "/proc/sys/net/ipv4/ip_forward" | grep -E -o "[^/]+/?$"

    进一步,取出其路径名:

    [root@node2 ~]# echo "/proc/sys/net/ipv4/ipforward/" | grep -E -o "^/.*/\b"

    5、找出ifconfig 命令结果中的 1-255 之间的数值;

    [root@node2 ~]# ifconfig | grep -E -o "\<([1-9]|[1-9][0-9]|1[1-9][0-9]|2[0-4][0-9]|25[0-5])\>"

    6、找出ifconfig命令结果中的IP地址;

    [root@node2 ~]# ifconfig | grep -E -o "\<([1-9]|[1-9][0-9]|1[1-9][0-9]|2[0-4][0-9]|25[0-5])\>.\<([1-9]|[1-9][0-9]|1[1-9][0-9]|2[0-4][0-9]|25[0-5])\>.\<([1-9]|[1-9][0-9]|1[1-9][0-9]|2[0-4][0-9]|25[0-5])\>.\<([1-9]|[1-9][0-9]|1[1-9][0-9]|2[0-4][0-9]|25[0-5])\>"
    172.26.255.255
    172.17.255.255
    192.168.2.12
    192.168.2.255
    
    [root@node2 ~]# ifconfig | grep -E -o "(\<([1-9]|[1-9][0-9]|1[1-9][0-9]|2[0-4][0-9]|25[0-5])\>.){3}(\<([1-9]|[1-9][0-9]|1[1-9][0-9]|2[0-4][0-9]|25[0-5])\>)"
    

    7、添加用户 bash,testbash,basher以及nologin(其shell为/sbin/nologin);而后找出/etc/passwd文件中用户名同shell名的行;

    [root@node2 ~]# grep -E "^([[:alnum:]_]+\b).*\1$" /etc/passwd

    [root@node2 ~]# grep -E "^([^:]+\>).*\1$" /etc/passwd

    2.3 fgrep

    fgrep 不支持正则表达式元字符。

    当无需用到元字符去编写模式时,使用 fgrep 性能更好。

    3 文本查看及处理工具:wc,cut,sort,uniq,diff,patch

    3.1 wc

    wc - word count,print newline, word, and byte counts for each file

    使用格式:wc [OPTION]... [FILE]...

    常用选项:

    • -l :lines,统计行数

    • -w :words,统计单词数

    • -c :bytes,统计字节数

    3.2 cut

    cut - 文本截取工具,remove sections from each line of files

    使用格式:cut OPTION... [FILE]...

    常用选项:

    • -d CHAR:以指定的字符为分隔符

    • -f fields: 挑选出的字段

      • #:指定的单个字段

      • #,#[,#]:离散的多个字段

      • #-# :连续的多个字段

      • --output-delimiter=STRING :指明输出时的分隔符

    3.3 sort

    sort - sort lines of text files

    使用格式:sort [OPTION]... [FILE]...

    常用选项:

    • -f :忽略字母大小写

    • -r :逆序显示

    • -t CHAR :指定字段分隔符

    • -k # :以指定字段为标准排序

    • -n :以数值大小进行排序

    • -u :uniq,重复的行只保留一份

      • 重复的行:连续且相同方为重复

    3.4 unique

    uniq - report or omit repeated lines,报告或移除重复的行

    使用格式:uniq [OPTION]... [INPUT [OUTPUT]]

    • -c :显示每行重复出现的次数

    • -d :仅显示重复过的行

    • -u :仅显示不曾重复的行

    练习:以冒号分隔,取出/etc/passwd文件的第6至第10行的各自的第1个字段,并将这些信息按第三个字段的数值大小排序

    head -10 /etc/passwd | tail -5 | sort -t: -k3 -n | cut -d:-f1

    练习:取出 ifconfig ens33 命令结果中的 ip 地址

    [root@node2 ~]# ifconfig ens33 | grep "inet\>" | cut -d" " -f10
    192.168.2.12
    

    3.5 diff 和 patch

    diff - compare files line by line,逐行比较文件中的内容

    使用格式:diff [OPTION]... FILES

    dff /PATH/TO/OLDFILE /PATH/TO/NEWFILE > /PATH/TO/PATCH_FILE

    • -u :使用 unfield 机制,即显示要修改的行的上下文,默认为3行

    patch - apply a diff file to an original,向文件打补丁

    使用格式:

    patch [OPTIONS] -i /PATH/TO/PATCH_FILE /PATH/TO/OLDFILE

    patch /PATH/TO/OLDFILE < /PATH/TO/PATCH_FILE

    范例:

    [root@node2 ~]# cp /etc/fstab ./
    [root@node2 ~]# cp fstab fstab.new
    [root@node2 ~]# vim fstab.new
    [root@node2 ~]# diff fstab fstab.new
    2c2    
    < #    
    ---
    > # comment       
    
    [root@node2 ~]# diff fstab fstab.new > fstab.patch    # 比较原文件和新文件的不同之处,将结果保存在 补丁文件中
    
    [root@node2 ~]# patch -i fstab.patch fstab # 对原文件打补丁
    patching file fstab
    [root@node2 ~]# patch -R -i fstab.patch fstab # 还原文件,逆向打补丁
    patching file fstab
    

    4 sed

    4.1 sed 工作模式

    image

    4.2 sed 使用格式

    使用格式:sed [option]... 'script' inputfile...

    script:

    • 地址定界编辑命令

    常用选项:

    • -n:不输出模式空间中的内容至屏幕
    • -i[SUFFIX], --in-place[=SUFFIX]:直接编辑原文件,慎用
    • -e script,--expression=script:多点编辑
    • -f /PATH/TO/SED_SCRIPT_FILE:从指定文件中读取编辑脚本
      • 每行一个编辑命令
    • -r:支持使用扩展正则表达式

    地址定界:

    (1)空地址,是对全文进行处理
    (2)单地址

    • #:指定行

    • /pattern/:被此处模式所能匹配到的每一行

    (3)地址范围

    • #,# :从第几行到第几行

    • #,+# :从第几行加多少行为止

    • #,/pat1/:从指定的行开始到第一次能够被模式所匹配到的行结束

    • /pat1/,/pat2/:从pat1模式匹配到pat2模式匹配

    (4)步进:~

    • 1~2:从第一行开始,每两行进行处理,即所有奇数行  
    • 2~2:从第二行开始,每两行进行处理,即所有偶数行

    (5)$:最后一行

    编辑命令:

    • d:删除模式空间中匹配到的行
    • p:显示模式空间中匹配到的行
    • a \text:模式空间中匹配到的行后面添加内容,支持使用\n 实现多行追加
    • i \text:模式空间中匹配到的行前面插入内容,支持使\n 实现多行插入
    • c \text:将匹配到的行替换为此处指定的文本”text“
    • w /PATH/TO/SOMEFILE:保存模式空间中匹配到的行至指定文件中
    • r /PATH/FORM/SOMEFILE:读取指定文件的内容至模式空间中匹配到的行后面;文件合并;
    • =:为模式空间中匹配到的行打印行号
    • !:取反条件
      • 地址定界!编辑命令
    • s///:查找替换,其分隔符可自行指定,常用的有s@@@,s###等
    • 替换标记:
      • g:行内全局替换
      • p:显示替换成功的行
      • w /PATH/TO/SOMEFILE:将替换成功的结果保存至指定文件中

    4.3 sed 示例

    1. d命令
      删除uuid开头的行
      [root@localhost ~]# sed '/^UUID/d' /etc/fstab
      删除空白行
      [root@localhost ~]# sed '/^$/d' /etc/fstab
      删除指定行,比如删除1-4行
      [root@localhost ~]# sed '1,4d' /etc/fstab

    2. p命令
      显示UUID开头的行
      [root@localhost ~]# sed '/^UUID/p' /etc/fstab
      这样的结果中不匹配到的行也会打印而且匹配到的行会打印两遍,可以使用-n不显示默认打印

    3. a \text
      [root@localhost ~]# sed '/^UUID/a \hello\nworld' /etc/fstab  //可以添加多行,\n

    4. i \text
      [root@localhost ~]# sed '/^UUID/i \helloworld\nmy' /etc/fstab //可以添加多行,\n

    5. c \text
      [root@localhost ~]# sed '/^UUID/c \uuid' /etc/fstab

    6. w FILE
      [root@localhost ~]# sed '/^UUID/w /tmp/a.txt' /etc/fstab

    7. r FILE
      [root@localhost ~]# sed '6r /etc/issue' /etc/fstab

    8. =
      [root@localhost ~]# sed '/^UUID/=' /etc/fstab

    9. !

      [root@node2 ~]# sed '/^#/!d' /etc/fstab //删除不以#开头的行

    10. sed
      将UUID替换为小写
      [root@localhost ~]# sed 's@UUID@uuid@' /etc/fstab
      删除/boot/grub/grub.conf文件中所有以空白开头的行行首的空白字符
      [root@localhost ~]# sed 's@^[[:space:]]\+@@' /boot/grub/grub.conf
      删除/etc/fstab文件中所有以#开头,后面至少跟一个空白字符的行的行首的#和空白字符
      [root@localhost ~]# sed 's@^#[[:space:]]*@@' /etc/fstab
      echo一个绝对路径给sed命令,取出其基名,取出其目录名
      路径名:[root@localhost ~]# echo "/etc/rc.d/rc3.d/init/" | sed 's@[^/]\+/\?$@@'
      基名:[root@localhost ~]# echo "/etc/rc.d/rc3.d/init/" | sed 's@^/.*/\([^/]\+/\?\)@\1@'

    11. -e 多点编辑

      [root@node2 ~]# sed -e 's@^#[[:space:]]*@@' -e '/^UUID/d' /etc/fstab

    高级编辑命令:

    • h:将模式空间中的内容覆盖至保持空间中
    • H:将模式空间中的内容追加至保持空间中
    • g:将保持空间中的内容覆盖至模式空间中
    • G:将保持空间中的内容追加至模式空间中
    • n:覆盖读取匹配到的行的下一行至模式空间中,此时,原有的行被覆盖掉
    • N:追加读取匹配到的行的下一行至模式空间中
    • d:删除模式空间中匹配到的行
    • D:删除多行模式空间中的所有行
    • x:把模式空间中的内容与保持空间中的内容互换

    示例:

    sed -n 'n;p' FILE:显示偶数行
    sed '1!G;h;$!d' FILE: 逆序显示文件内容
    sed '$!N;$!D' FILE:取出文件后两行
    sed '$!d' FILE: 取出最后一行
    sed 'G' FILE: 每行下面添加一个空白行
    sed '/^$/d;G' FILE 删除原有的所有空白行,而后为所有的非空白行后添加一个空白行
    sed 'n;d' FILE: 显示奇数行
    sed -n '1!G;h;$p' FILE:逆向显示文件中的每一行
    

    5 AWk

    5.1 awk 简介

    awk:报告生成器,格式化文本输出

    AWK:Aho,Weinberger,Kernighan --> New AWK,NAWK

    gawk - pattern scanning and processing language

    在 linux系统上,awk 是指向 gawk 命令的链接。

    5.2 awk 工作模式

    image

    它的工作模式是对文本逐行进行处理,将每一行文本按照输入时分隔符(默认分隔符为空白字符)切片,把每一个切片直接保存在用awk内建的变量中,然后可以对每一片内容进行输出、循环等操作。如果要显示整行内容用 $0 来表示。

    5.3 awk 使用格式 和 常用选项

    基本用法:awk [options] 'program' FILE...

    program: PATTERN{ACTION STATEMENTS},语句之间用分号分隔

    常用选项:

    • -F:指明输入时用到的字段分隔符
    • -v var=VALUE:自定义变量

    示例:

    1、/etc/fstab 文件中以 UUID 开头的行,打印第2 和 第 4个字段

    [root@localhost scripts]# awk '/^UUID/{print $2,$4}' /etc/fstab
    /boot defaults
    swap defaults
    

    2、指明输入时字段分隔符为 : ,打印第1个切片内容,比如对/etc/passwd处理

    [root@localhost scripts]# awk -F: '{print $1}' /etc/passwd
    root
    bin
    daemon
    

    3、使用内建变量FS指明输入时的分给福为冒号,打印第一个片段的内容

    [root@node2 ~]# awk -v FS=":" '{print $1}' /etc/passwd
    root
    bin
    daemon
    

    5.4 常用命令

    5.4.1 print

    使用格式:print item1,item2,...
    要点:
    (1)item之间用逗号分隔
    (2)输出的各item可以是字符串,也可以是数值;也可以是当前记录的字段、变量或awk的表达式;
    (3)如果省略item,相当于 print $0,打印整行内容

    范例:

    print后面不跟 item 时,是将整行内容输出,相当于 print $0

    [root@node2 ~]# awk '{print}' /etc/passwd
    root:x:0:0:root:/root:/bin/bash
    bin:x:1:1:bin:/bin:/sbin/nologin
    

    对比一下:如果是 print "",结果是?

    [root@node2 ~]# awk '{print ""}' /etc/passwd    	显示空白行
    
    5.4.2 变量
    5.4.2.1 内建变量
    • FS:input field seperator,输入时的分隔符,默认为空白字符

    • OFS:output field seperator,输出时的分隔符,默认为空白字符

    • RS:input record seperator,输入时的换行符

    • ORS:output record seperator,输出时的换行符

    • NF:number of field,字段数量

    • NR:number of record,行数

    • FNR:各文件分别计数:行数

    • FILENAME:当前文件名

    • ARGC:命令行参数的个数

    • ARGV:数组,保存的是命令行所给定的各参数

    内建变量相关示例
    1、FS:指明输入时的分隔符为冒号,打印第一个片段

    [root@node2 ~]# awk -v FS=':' '{print $1}' /etc/passwd
    root
    bin
    

    2、OFS:指明输入时分隔符为冒号,输出时分隔符为@@,打印第2、3、7 字段

    [root@node2 ~]# awk -F: -v OFS='@@' '{print $2,$3,$7}' /etc/passwd
    x@@0@@/bin/bash
    x@@1@@/sbin/nologin
    x@@2@@/sbin/nologin
    

    3、RS:指明输入时的换行符为'o',打印第1、3 片段

    [root@localhost scripts]# awk -v RS='o' '{print $1,$3}' /etc/passwd
    

    4、ORS:指明输出时的换行符为'##'

    [root@node2 ~]# awk -v RS=':' -v ORS='##' '{print $0}' /etc/passwd
    root##x##0##0##root##/root##/bin/bash
    bin##x##1##1##bin##/bin##/sbin/nologin
    

    5、NF

    显示每行多少段

    [root@node2 ~]# awk -F: '{print NF}' /etc/passwd
    7
    7
    

    显示最后一个片段的值

    [root@node2 ~]# awk -F: '{print $NF}' /etc/passwd
    /bin/bash
    /sbin/nologin
    /sbin/nologin
    

    6、NR

    显示每一行的行数

    [root@localhost scripts]# awk '{print NR}' /etc/passwd
    1
    2
    

    对比一下 $NR 打印的值

    [root@node2 ~]# awk -F: '{print $NR}' /etc/passwd
    root
    x
    2
    4
    lp
    /sbin
    /sbin/shutdown
    

    7、FNR

    显示 /etc/passwd 和 /etc/fstab 两个文件的行号

    [root@node2 ~]# awk '{print FNR}' /etc/passwd /etc/fstab
    1
    2
    3
    1
    2
    3
    4
    

    8、FILENAME

    [root@node2 ~]# awk '{print FILENAME}' /etc/fstab
    /etc/fstab
    /etc/fstab
    

    9、ARGC 和 ARGV

    [root@node2 ~]# awk 'BEGIN{print ARGC}' /etc/fstab /etc/passwd
    3
    
    [root@node2 ~]# awk 'BEGIN{print ARGV[0]}' /etc/fstab /etc/passwd
    awk
    [root@node2 ~]# awk 'BEGIN{print ARGV[1]}' /etc/fstab /etc/passwd
    /etc/fstab
    [root@node2 ~]# awk 'BEGIN{print ARGV[2]}' /etc/fstab /etc/passwd
    /etc/passwd
    
    5.4.2.2 自定义变量

    (1)-v var=value

    (2)在program中直接定义

    示例:

    [root@node2 ~]# awk -v test="hello awk" 'BEGIN{print test}'
    hello awk
    
    [root@node2 ~]# awk 'BEGIN{test="hello awk";print test}'
    hello awk
    
    5.4.3 printf

    格式化输出:printf FORMAT,item1,item2,...

    要点:

    (1)FORMAT 必须给出

    (2)不会自动换行,需要显示给出换行控制符,\n

    (3)FORMAT中需要分别为后面的每个item指定一个格式化符号

    格式符:

    • %c:显示字符的ASCII码
    • %d,%i:显示十进制整数
    • %e,%E:科学计数法数值显示
    • %f:显示为浮点数
    • %g,%G:以科学计数法或浮点形式显示数值
    • %s:显示字符串
    • %u:无符号整数
    • %%:显示%自身

    修饰符:

    • #[.#]:第一个#数字控制显示的宽度,第二个#表示小数点后的精度,比如 %3.1f
      • 默认是右对齐
      • - :左对齐
      • + :显示数值的符号

    范例:

    [root@node2 ~]# awk -F: '{printf "username:%s\n",$1}' /etc/passwd
    username:root
    username:bin
    username:daemon
    username:adm
    username:lp
    

    如果要显示两个字段:默认是右对齐

    [root@node2 ~]# awk -F: '{printf "Username:%s,Uid:%d\n",$1,$3}' /etc/passwd
    Username:root,Uid:0
    Username:bin,Uid:1
    Username:daemon,Uid:2
    

    第一个字段设置字符串宽度为 15:

    [root@node2 ~]# awk -F: '{printf "Username:%15s,Uid:%d\n",$1,$3}' /etc/passwd
    Username:           root,Uid:0
    Username:            bin,Uid:1
    Username:         daemon,Uid:2
    

    第一个字段设置宽度为 15,并且设置为左对齐:

    [root@node2 ~]# awk -F: '{printf "Username:%-15s,Uid:%d\n",$1,$3}' /etc/passwd
    Username:root           ,Uid:0
    Username:bin            ,Uid:1
    Username:daemon         ,Uid:2
    
    5.4.4 操作符
    • 算术操作符
      • x+y,x-y,x*y,x/y,x^y,x%y
      • -x :把一个整数转为负数
      • +x :把一个字符串转换为数值
    • 字符串操作符 :没有符号的操作符,字符串连接之意
    • 赋值操作符
      • =,+=,-=,*=,/=,%=,^=
      • ++,--
    • 比较操作符
      • >,>=,<,<=,!=,==
    • 模式匹配符
      • ~:左侧的字符串是否能够被右侧的模式所匹配
      • !~:左侧的字符串是否不能够被右侧的模式所匹配
    • 逻辑操作符
      • &&
      • ||
    • 函数调用
      • function_name(arg1,arg2,...)
    • 条件表达式
      • selector?if-true-expression:if-false-expression
      • 条件表达式示例

    条件表达式示例:

    显示 id 号大于1000 为系统用户,小于等于1000为普通用户

    [root@node2 ~]# awk -v FS=':' '{$3>1000?usertype="common user":usertype="sysadm";printf "%-15s:%-15s,Uid:%d\n",usertype,$1,$3}' /etc/passwd
    sysadm         :root           ,Uid:0
    sysadm         :chrony         ,Uid:997
    common user    :hadoop         ,Uid:1001
    common user    :centos         ,Uid:1002
    
    5.4.5 PATTERN

    (1)empty:空模式,匹配每一行

    示例:空模式,即匹配到每一行

    [root@node2 ~]# awk -F: '{print $1}' /etc/passwd
    root
    bin
    daemon
    

    (2)/regular expression/:仅处理能够被此处的模式匹配到的行

    示例:显示以 UUID 开头的行:

    [root@node2 ~]# awk -F: '/^UUID/{print}' /etc/fstab
    UUID=f1a9b50d-7606-449c-90ae-a39f421cc685 /boot                   ext4    defaults        1 2
    UUID=74a2b3e5-775e-48d5-b26d-48358ebdd1c8 swap                    swap    defaults        0 0
    

    (3)relational expression:关系表达式,结果有”真“有“假”;结果为”真“才会被处理

    • 真:结果为非0值,非空字符串

    示例:显示 uid 大于 1000 的行:

    [root@node2 ~]# awk -F: '$3>1000{print}' /etc/passwd
    hadoop:x:1001:1001::/home/hadoop:/bin/bash
    centos:x:1002:1002::/home/centos:/bin/bash
    

    判断最后一个片段的值是否为 /bin/bash,如果是就打印出第 1 和 7 个片段:

    [root@node2 ~]# awk -F: '$NF=="/bin/bash"{print $1,$7}' /etc/passwd
    root /bin/bash
    chegnkaihua /bin/bash
    hadoop /bin/bash
    

    判断最后一个片段能够被右侧的模式所匹配,匹配的话就打印第1和第7个字段:

    [root@node2 ~]# awk -F: '$NF~/bash$/{print $1,$7}' /etc/passwd
    root /bin/bash
    chegnkaihua /bin/bash
    hadoop /bin/bash
    

    (4)line ranges:行范围

    • startline,endline;/pat1/,/pat2/

    注意:不支持直接给出数字的格式

    示例:显示 第10行到第15行范围内的内容:

    [root@node2 ~]# awk -F: 'NR>10&&NR<=15{print}' /etc/passwd
    games:x:12:100:games:/usr/games:/sbin/nologin
    ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
    nobody:x:99:99:Nobody:/:/sbin/nologin
    systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
    dbus:x:81:81:System message bus:/:/sbin/nologin
    

    显示 匹配root开头的行到匹配daemon开头的行中间的内容:

    [root@node2 ~]#  awk -F: '/^root/,/^daemon/{print}' /etc/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
    

    (5)BEGIN/END模式

    • BEGIN{}:仅在开始处理文本之前执行一次
    • END{}:仅在文本处理完成之后执行一次
      [root@localhost scripts]# awk -F: 'BEGIN{print " USERNAME UID \n-------------------------------"}{printf "%15s,%10d", $1,$3}END{print "====================\n end"}' /etc/passwd

    示例:

    [root@node2 ~]# awk -F: 'BEGIN{print "        Username       Uid        \n------------------------"}{printf "%15s,%10d\n",$1,$3}END{print "=======================\n        end         "}' /etc/passwd
            Username       Uid
    ------------------------
               root,         0
                bin,         1
             daemon,         2
                adm,         3
                 lp,         4
    =========================
              end
    
    5.4.6 常用的action

    (1)Expresstions
    (2)Control statements:if,while等
    (3)Compound statements:组合语句
    (4)input statements
    (5)output statements

    5.4.7 控制语句
    if(condition) {statements}
    if(condition) {statements} else {statements}
    while(condition) {statements}
    do{statements} while(condition)
    for(expr1;expr2;expr3) {statements}
    break
    continue
    delete aray[index]
    delete array
    exit
    { statements }
    

    7.1 if-else
    语法:if(condition) statement [else statement]
    使用场景: 对awk取得的整行或某个字段做条件判断;

    示例:

    1. id号大于500为普通用户,其他为系统用户
    [root@node2 ~]# awk -F: -v OFS=':' '{if($3>500){usertype="common user"} else {usertype="Sysadm"} print usertype,$1,$3}' /etc/passwd
    Sysadm:root:0
    Sysadm:ntp:38
    common user:chrony:997
    common user:hadoop:1001
    common user:centos:1002
    
    1. 以/bin/bash结尾的字段
    [root@node2 ~]# awk -F: '{if($NF=="/bin/bash"){print}}' /etc/passwd
    root:x:0:0:root:/root:/bin/bash
    chegnkaihua:x:1000:1000:chegnkaihua:/home/chegnkaihua:/bin/bash
    hadoop:x:1001:1001::/home/hadoop:/bin/bash
    
    1. 每行片段大于5个,则显示整行
    [root@node2 ~]# awk -F: '{if(NF>5){print}}' /etc/passwd
    root:x:0:0:root:/root:/bin/bash
    bin:x:1:1:bin:/bin:/sbin/nologin
    
    1. df命令中use大于百分之20的设备
    [root@node2 ~]# df -h | awk -F% '/^\/dev/{print $1}' | awk '{if($NF>20){print $0}}'
    /dev/mapper/centos-root  4.8G  3.5G  1.1G   77
    /dev/sda1                190M   99M   77M   57
    /dev/mapper/centos-var   2.9G  2.3G  524M   82
    

    7.2 while循环
    语法:while(condition)statement
    条件为"真",进入循环,条件为"假",退出循环
    使用场景: 对一行内的多个字段逐一类似处理时使用;对数组中的各元素逐一处理时使用

    示例:

    1. 对空白字符开头的行,每个片段的字符个数统计
    [root@node2 ~]# awk '/^[[:space:]]*/{i=1;while(i<=NF){print $i,length($i);i++}}' /etc/grub2.cfg
    # 1
    the 3
    'exec 5
    tail' 5
    line 4
    above. 6
    ### 3
    END 3
    
    [root@node2 ~]# awk '/^[[:space:]]*linux16/{i=1;while(i<=NF) {if(length($i)>=7){print $i,length($i)}; i++}}' /etc/grub2.cfg
    

    7.3 do-while循环
    语法:do statement while(condition)

    意义:至少执行一次循环体

    7.4 for循环
    语法:for(expr1;expr2;epr3) statement

    示例:

    [root@node2 ~]# awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++){print $i,length($i)}}' /etc/grub2.cfg
    linux16 7
    /vmlinuz-5.12.0-1.el7.elrepo.x86_64 35
    root=/dev/mapper/centos-root 28
    ro 2
    crashkernel=auto 16
    console=ttyS0 13
    console=tty0 12
    panic=5 7
    linux16 7
    /vmlinuz-0-rescue-41c2d068d302c7418c1eea55178030b5 50
    root=/dev/mapper/centos-root 28
    ro 2
    crashkernel=auto 16
    console=ttyS0 13
    console=tty0 12
    panic=5 7
    

    特殊用法:能够遍历数组中的元素
    语法:for(var in array) {for-body}

    7.5 switch语句
    语法: switch(expression) {case VALUE1 or /REGEXP1/:statement;case VALUE2 or /REGEXP2/;statement;...;default:statement}

    7.6 break 和 continue
    break [n]
    continue

    7.7 next
    提前结束对本行的处理而直接进入下一行

    示例:显示偶数行

    [root@localhost scripts]# awk -F: '{if($3%2!=0) next;print $1,$3}' /etc/passwd
    root 0
    daemon 2
    lp 4
    
    5.4.8 array

    支持关联数组:array[index-expression]
    index-expression:
    (1)可使用任意字符串;字符串要使用双引号;
    (2)如果某数组元素事先不存在,在引用时,awk会自动创建此元素,并将其值初始化为"空串" 

    若要判断数组中是否存在某元素,要使用"index in array"格式进行

    示例:

    1. 给数组赋值并打印第一个值
    [root@localhost scripts]# awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";print weekdays["mon"]}'
    Monday
    
    1. 若要遍历数组中的每个元素,要使用for循环
    [root@localhost scripts]# awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";for(i in weekdays){print weekdays[i]}}'
    Monday
    Tuesday
    

    注意:var 会遍历array的每个索引

    1. 统计 netstat -atn 命令结果中各状态结果的出现次数
    [root@node2 ~]# netstat -atn | awk '/^tcp\>/{state[$NF]++}END{for(i in state){print i,state[i]}}'
    LISTEN 6
    ESTABLISHED 2
    SYN_SENT 11
    
    1. 统计每个 ip 访问了多少次
    [root@node2 ~]# awk '{ip[$1]++}END{for(i in ip){print i,ip[i]}}' /var/log/httpd/access_log
    192.168.2.11 2
    192.168.2.12 2
    192.168.2.122 1
    192.168.2.13 4
    192.168.2.1 8
    192.168.2.133 1
    
    1. 统计/etc/fstab文件中各文件系统类型出现的次数
    [root@node2 ~]# awk '/^[^#]/{fstype[$3]++}END{for(i in fstype){print i,fstype[i]}}' /etc/fstab
    swap 1
    ext4 4
    
    1. 统计 /etc/fstab 文件中每个单词出现的次数
    [root@node2 ~]# awk '{for(i=1;i<=NF;i++){words[$i]++}}END{for(i in words){print i,words[i]}}' /etc/fstabman 12021 1and/or 1maintained 1/dev/mapper/centos-root 1UUID=f1a9b50d-7606-449c-90ae-a39f421cc685 1/var 1Accessible 1# 7/dev/mapper/centos-home 1Apr 1
    
    5.4.9 函数

    9.1 内置函数

    • 数值处理

      • rand():返回0和1之间一个随机数
    • 字符串处理

      • length([s]):返回指定字符串的长度
      • sub(r,s,[t]):以 r 表示的模式来查找 t 所表示的字符中的匹配的内容,并将其第一次出现替换为 s 所表示的内容.也就是将t中的内容 r替换为 s
      • gsub(r,s,[t]):以 r 表示的模式来查找 t 所表示的字符中的匹配的内容,并将其所有出现替换为 s 所表示的内容.也就是将t中的内容 r替换为 s
      • split(s,a[],r):以 r 为分隔符切割字符串 s,并将切割后的结果保存至 a 所表示的数组中
        注意:awk中的数组从1开始编号

    示例:返回 0 和 1 之间的一个随机数:

    [root@localhost ~]# awk 'BEGIN{print rand()}'
    0.237788
    

    示例:/etc/passwd 中第一个片段中的 o 替换为 O:

    [root@node2 ~]# awk -F: 'BEGIN{print sub(o,O,$1)}' /etc/passwd
    1
    

    示例:统计 netstat -atn 命令中客户端连接的 ip出现次数,采用 split 分隔符

    [root@node2 ~]# netstat -atn | awk '/^tcp\>/{split($4,ip,":");count[ip[1]]++}END{for(i in count){print i,count[i]}}'
    127.0.0.1 5
    0.0.0.0 1
    192.168.2.12 14
    

    9.2 自定义函数

    参考书籍:<<sed和awk>>

  • 相关阅读:
    POJ 1987
    POJ 3107
    POJ 1984
    POJ 1985
    【50】目标检测之目标定位
    【49】计算机视觉现状
    【48】数据扩充(Data augmentation)
    【47】迁移学习(Transfer Learning)
    【46】谷歌 Inception 网络简介Inception(2)
    【45】谷歌 Inception 网络简介Inception(1)
  • 原文地址:https://www.cnblogs.com/ckh2014/p/14804490.html
Copyright © 2011-2022 走看看