• linux中awk的使用


    参考文献:https://www.cnblogs.com/jiqianqian/p/7944013.html

    awk是一个强大的文本分析工具。相较于sed常常一整行处理,awk则倾向于将一行数据切片,分成数个“字段”处理;简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理。

    语法:

    awk '条件类型1{动作1} 条件类型2{动作2} ...' filename
    awk [options] 'pattern{action}' file

     1.查看最近5条登录用户和ip地址

    awk工作流程是这样的:读入有’ ’换行符分割的一条记录,然后将记录按指定的域分隔符划分域,填充域,01表示第一个域,nn"""[tab]"1表示登录用户,$3表示登录用户ip,以此类推。

    $ last -n 2|awk '{print $1"	"$3}'
    lzyer    192.168.56.1
    reboot    boot
    $ last -n 2|awk '{print $1,$3}'
    lzyer 192.168.56.1
    reboot boot
    只处理第一行的数据
    $ last -n 2|awk 'NR==1{print $1,$3}' lzyer 192.168.56.1

    2.print和printf

    参考:https://www.cnblogs.com/soymilk2019/p/12165545.html

    awk中同时提供了print和printf两种打印输出的函数。

    其中print函数的参数可以是变量、数值或者字符串字符串必须用双引号引用,参数用逗号分隔。如果没有逗号,参数就串联在一起而无法区分。这里,逗号的作用与输出文件的分隔符的作用是一样的,只是后者是空格而已。

    printf函数用来格式化字符串,输出复杂时,printf更加好用,代码更易懂。

    1. 使用printf输出的文本不会换行,如果需要换行,可以在对应的“格式替换符”后加入“ ”进行转义

    2. 使用printf输出时,“指定的格式”与“被格式化的文本”之间,要用“,”隔开

    3. 使用printf输出时,“格式”中的“格式替换符”必须与“被格式化的文本”一一对应(个数要相同)

    eg:

    1.#awk -F ':' '{print "filename:" FILENAME ",linenumber:" NR ",columns:" NF ",linecontent:"$0}' /etc/passwd 
    输出:filename:/etc/passwd,linenumber:1,columns:7,linecontent:root:x:0:0:root:/root:/bin/bash 2.awk -F ':' '{printf("filename:%10s,linenumber:%s,columns:%s,linecontent:%s ",FILENAME,NR,NF,$0)}' /etc/passwd
    输出:filename:/etc/passwd,linenumber:1,columns:7,linecontent:root:x:0:0:root:/root:/bin/bash
     printf函数用来格式化特别的输出,printf函数返回一个带格式的字符串给标准输出,printf语句包括一个加引号的控制串,控制串中可能嵌有若干格式说明和修饰符。控制串后面跟一个逗号,之后是一列由逗号分隔的表达式。printf函数根据控制串中的说明编排这些表达式的格式。与print函数不同的是, printf不会在行尾自动换行。因此,如果要换行,就必须在控制串中提供转义字符 。
    每一个百分号和格式说明都必须有一个对应的变量。要打印百分号就必须在控制串中给出两个百分号。请参考print转义字符和printf修饰符。格式说明由百分号引出,另外还列出了printf所用的格式说明符。
    printf使用的转义字符
    转义字符
    定义
    修饰符
    定义
    c
    字符
    -
    左对齐修饰符
    s
    字符串
    #
    显示8 进制整数时在前面加个0
    显示16 进制整数时在前面加0x
    d
    十进制整数
    +
    显示使用d 、e 、f 和g 转换的整数时,加上正负号+或-
    ld
    十进制长整数
    0
    用0而不是空白符来填充所显示的值
    u
    十进制无符号整数
    格式说明符
    功能
    lu
    十进制无符号长整数
    %c
    打印单个ASCII 字符
    printf("The character is %c ",x) 输出: The character is A
    x
    十六进制整数
    %d
    打印一个十进制数
    printf("The boy is %d years old ",y) 输出:The boy is 15 years old
    lx
    十六进制长整数
    %e
    打印数字的e 记数法形式
    printf("z is %e ",z) 打印: z is 2.3e+0 1
    o
    八进制整数
    %f
    打印一个浮点数
    printf("z is %f ", 2.3 * 2) 输出: z is 4.600000
    lo
    八进制长整数
    %o
    打印数字的八进制
    printf("y is %o ",y) 输出:z is 17
    e
    用科学记数法(e 记数法)表示的浮点数
    %s
    打印一个字符串
    print("The name of the culprit is %s ",$1) 输出:The name of the culprit is Bob Smith
    f
    浮点数
    %x
    打印数字的十六进制值
    printf("y is %x ",y) 输出:x is f
    g
    选用e或f中较短的一种形式
       
     
    打印变量时,输出所在的位置称为"域"(field),域的宽度(width)是指该域中所包含的字符个数。下面这些例子中, printf控制串里的管道符(竖杠)是文本的一部分, 用于指示格式的起始与结束。
     
    范例 $ echo "Linux" | awk '{printf "|%-15s| ",$1}'
    |Linux          |
    说明:对于echo命令的输出,Linux是经管道发给awk。printf函数包含一个控制串。百分号让printf做好准备,它要打印一个占15个格、向左对齐的字符串,这个字符串夹在两个竖杠之间,并且以换行符结尾。百分号后的短划线表示左对齐。控制串后面跟了一个逗号和$1。printf将根据控制串中的格式说明来格式化字符串Linux。
    范例 $ echo "Linux" | awk '{printf "|%15s| ",$1}'
    |          Linux|
    说明:字符串Linux被打印成一个占15 格、向右对齐的字符串,夹在两个竖杠之间,以换行符结尾。
    范例 $ cat employees
    Tom   Jones 4424 5/12/66 543354
    Mary  Adams 5346 11/4/63 28765
    Sally Chang 1654 7/22/54 650000
    Billy Black 1683 9/23/44 336500
    $ awk '{printf "The name is: %-15s ID is %8d ",$1,$3}' employees
    The name is Tom             ID is 4424
    The name is Mary            ID is 5346
    The name is Sally           ID is 1654
    The name is Billy           ID is 1683
    说明:要打印的字符串放置在两个双引号之间。第一个格式说明符是%-15s,它对应的参数是$1,紧挨着控制串的右半边引号后面的那个逗号。百分号引出格式说明:短划线表示左对齐,15s表示占15格的字符串。这条命令用来打印一个左对齐、占15格的字符串,后面跟着字符串的ID和一个整数。
    格式:%8d表示在字符串的这个位置打印$2 的十进制(整数)值。这个整数占8格,向右对齐。您也可以选择将加引号的字符串和表达式放在圆括号里。

    3.正则匹配

    搜索/etc/passwd有root关键字的所有行

    awk -F: '/root/' /etc/passwd
    输出:root:x:0:0:root:/root:/bin/bash

    这种是pattern的使用示例,匹配了pattern(这里是root)的行才会执行action(没有指定action,默认输出每行的内容)。

    搜索/etc/passwd有root关键字的所有行,并显示对应的shell,这里指定了action{print $7}

    awk -F: '/root/{print $7}' /etc/passwd
    输出:/bin/bash
    匹配第四个字段中是否包含字符串“Techology”,若包含,打印该行
    awk '$4 ~/Technology/' employee.txt

     操作符〜是正则表达式比较。如果匹配的默认操作,即打印整行.

    4.awk内置变量

    awk有许多内置变量用来设置环境信息,这些变量可以被改变,下面给出了最常用的一些变量。

    ARGC 命令行参数个数 
    ARGV 命令行参数排列 
    ENVIRON 支持队列中系统环境变量的使用 
    FILENAME awk浏览的文件名 
    FNR 浏览文件的记录数 
    FS 设置输入域分隔符,等价于命令行 -F选项 
    NF 浏览记录的域的个数 
    NR 已读的记录数 
    OFS 输出域分隔符 
    ORS 输出记录分隔符 
    RS 控制记录分隔符

     5.常见用法

    1. -F指定分隔符,默认为空格

    awk -F: 'NR==1{print}' /etc/passwd
    root:x:0:0:root:/root:/bin/bash

    2. -v 替换变量

    var1=100
    echo |awk -v var=$var1 '{print var}'
    100

    3.使用内置变量FS指定输入分隔符,需要注意的是,使用变量时,要使用-v选项来指定对应的变量

    awk -v FS=":" 'NR==1{print}' /etc/passwd
    root:x:0:0:root:/root:/bin/bash
    
    awk -v FS=":" -v OFS="#" 'NR==1{print $1,$2}' /etc/passwd
    root#x

    指定多个分隔符[]

    1.指定多个分隔符
    [root@cxm ~]# cat 123
    1111111111*222222222222222|33333333333#4444444444444&5555555555555555
    #根据上边的文件,我们可以以* |#& 为分隔符
    [root@cxm ~]# awk -F '[*|#&]' '{print $3}' 123
    33333333333
    [root@cxm ~]# awk -F '[*|#&]' '{print $4}' 123
    4444444444444

     2.连续的分隔符为一个分隔符

    [root@cxm ~]# cat 222
    111111*****2222222|||||||3333333########444444444&&&&&&&&&55555555
    #在[]后边加个+(加号)
    [root@cxm ~]# awk -F '[*|#&]+' '{print $3}' 222
    3333333
    #默认连续不同的分隔符也会成为一个分隔符
    [root@cxm ~]# cat 333
    111111*|2222222|||||||3333333########444444444&&&&&&&&&55555555
    [root@cxm ~]# awk -F '[*|#&]+' '{print $3}' 333
    3333333
    #*和|变成了一个分隔符

    BEGIN、END 的使用

    语法:BEGIN { Actions}
    {ACTION} # Action for everyline in a file
    END { Actions } # is for comments in Awk
    举例:
    1.打印报告
    $ awk 'BEGIN {print "Name	Designation	Department	Salary";}
    > {print $2,"	",$3,"	",$4,"	",$NF;}
    > END{print "Report Generated
    --------------";}' employee.txt

     2.计算整个文档的第四个字段中包含Technology字符串的行数

    awk 'BEGIN {count=0;} $4 ~ /Technology/ {count++;} END {print "the number =",count;}' test_awk.txt

     6. 关系运算符

    关系运算符 含义 用法实例
    < 小于 x<y
    <= 小于等于 x<=y
    > 大于 x>y
    >= 大于等于 x>=y
    == 等于 x==y
    != 不等于 x!=y
    ~ 匹配 x~/正则表达式/
    !~ 不匹配 x!~/正则表达式/

    7.其他栗子

    1.awk 打印除某列之外的所有列
    1)awk '{ $3=""; print $0 }'   a.txt 将某列置为空,然后打印所有列。
    2)获取详细时间 stat  a.json|grep 'Modify'|awk '{print $2,$3}' #2018-11-09 08:46:43.314788880
    3)获取第二字段之后的所有值 stat  a.json|grep 'Modify'|awk '{$1=$2=""}1' #08:46:43.314788880 +0000
    4)获取最后一列的值 awk -F',' '{print $NF}'  a.txt ,最后一列的值用$NF表示,倒数第二列用$(NF-1)表示。
    5) 获取最后一行 awk 'END {print}' a.txt
    6)  获取文件中的某几行 cat 1.txt |awk '{if ($1=="关键字")print $0}'
     
    2.获取指定行的数据
    获取第二行的数据 ps -a|grep logwriter|awk 'NR==2'
    获取第一列第二列的数据 ps -a|grep logwriter|awk '{print $1,$2}' 
    获取第二行第二列的数据 ps -a|grep logwriter|awk -F ': ' 'NR==2{print $2}'
     
    3.awk打印从某一列到最后一列的内容
    awk '{for(i=2;i<=NF;i++) printf("%s ",$i);print ""}' test_awk.txt
    其中,print是分行打印,NF是最后一个域的索引值
     
    4. 求最后一列的和
    -F',' 指定分隔符为逗号,$NF为最后一列
    awk -F',' '{sum += $NF};END{print sum}'
     
    5.使用awk sed取出最后两个字段之外的字段
    源字符串aa='/data/1learn_linux/test1/test2/learn_sed.txt',现只想要获取/data/1learn_linux/test1这一部分
    1.使用sed
    bb=`echo $aa|awk -F'/' '{print $(NF-1)"/"$NF}'`
    echo $aa|sed -n "s@$bb@@gp" 由于字符串中含有/所以地址界定符用了@而不是/
    2.使用awk
    echo $aa |awk -F'/' '{gsub($(NF-1)"/"$NF,"");print}'
    gsub(regular expression, subsitution string, target string);简称 gsub(r,s,t)即将字符串t中的r全部替换称s,其中t为指定域,省略时就默认使用整个记录。
    sub匹配第一次出现的符合模式的字符串,相当于 sed 's//' 。
    gsub匹配所有的符合模式的字符串,相当于 sed 's//g' 。
    例如:
    awk '{sub(/Mac/,"Macintosh");print}' file 用Macintosh替换Mac
    awk '{sub(/Mac/,"MacIntosh",$1); print}' file 第一个域内用
     
    6.awk提取指定字符串
    路径名为 /home/ lxy/ hhhhh-a.bbb.cc.d (格式类型固定)
    其中 现在我只想要 a.bbb.cc 这一段。
    其中 hhhhh- 格式固定 ,a.bbb.cc.d 这一段长度有浮动,但前面的 a. 和后面的 .d 是固定的
    解决方法:
    如果/home/ lxy/ hhhhh-a.bbb.cc.d是文件中的字符串(即echo '/home/ lxy/ hhhhh-a.bbb.cc.d'>test.txt ),可以通过sed -n 's/.*hhhhh-(.*).d/1/p' test.txt
    其他方法:1.以'-'为分隔符,用cut取第二个字段(只要路径中不包含'-'即可):echo "/home/lxy/hhhhh-a.bbb.cc.d" | cut -d'-' -f2  但该方法只能取出a.bbb.cc.d
    2.为防止路径中有'-',可以先取出文件名,在使用cut:echo "/home/lxy/hhhhh-a.bbb.cc.d" | awk -F/ '{print $NF}'| cut -d'-' -f2 但该方法只能取出a.bbb.cc.d
    3.echo "/home/lxy/hhhhh-a.bbb.cc.d" | awk -F'-' '{print $2}' | cut -f 1-3 -d'.'
     
     
     




     
  • 相关阅读:
    Hadoop_10_12虚拟机01_虚拟机NAT方式联网【自己的亲测笔记】
    StringUtils中 isNotEmpty 和isNotBlank的区别【java字符串判空】
    SVM
    [python]小技巧集锦
    [机器学习&数据挖掘]SVM---核函数
    [机器学习&数据挖掘]SVM---软间隔最大化
    [机器学习]SVM---硬间隔最大化数学原理
    [机器学习&数据挖掘]朴素贝叶斯数学原理
    [机器学习&数据挖掘]机器学习实战决策树plotTree函数完全解析
    [机器学习]信息&熵&信息增益
  • 原文地址:https://www.cnblogs.com/mianbaoshu/p/9001995.html
Copyright © 2020-2023  润新知