zoukankan      html  css  js  c++  java
  • AWK简单使用方法

    1. 命令格式

    gawk [OPTIONS] 'program' FILES....
    program:'PATTERN{ACTION}'
    	一条awk命令中,PATTERN和ACTION,至少存在一个才可执行;
    		缺少PATTERN,则对输入行内容全部执行ACTION;
    		缺少ACTION,则所有匹配上PATTERN的输入行都会被输出;
    	在awk中使用分号“;”来分割语句;
    

    2. awk的执行过程

    awk读取一行,进行模式匹配,匹配了就执行相应的动作,没有匹配就忽略,读取下一行,重复此动作.

    3. 内置变量

    FS:输入文件的field分隔符,默认是空白字符;
    OFS:输出文件的field分隔符,默认是空白字符;
    RS:输入文件record分隔符,默认是
    ;
    ORS:输入文件record分隔符,默认是
    ;
    NF:每行的field数量,{print NF}表示显示当前行的field数量,{print $NF}表示显示当前行的最后一个field;
    NR:record数,对所有输入行进行统一排序;
    FNR:record数,对每个文件的输入行进行分别排序;
    FILENAME:输入文件的名字;
    ARGC:命令行中的参数个数;
    ARGV:数组,可以将当前命令行中的参数分别加入到ARGV这个数组中,从0开始;
    $1、$2、$3...$n:代表当前行中对应的field
    

    4. 常用OPTION

    -F:指定输入分隔符;
    -v:指定awk的变量;像FS、OSF、RS、ORS这些变量,就可以使用-v进行重新赋值;
    

    5. 双引号的作用

    定义一个变量superuser的值为root,但是打印的时候,发现打印出了一个空行,并没有实际内容
    [root@centos7 ~]# awk 'BEGIN{superuser=root;print superuser}'
    空行......
    
    这是因为只有加上了双引号才会被awk认为是字符串,否则会被认为是变量。在上面这个例子中,想要为superuser赋值的是root字符串,但是因为没有加上双引号,被awk认为root也是一个变量,但是awk中又不存在这个变量,所以最终为superuser的变量内容就是空。
    所以在awk中定义变量应该是这种情况:
    [root@centos7 ~]# awk 'BEGIN{superuser="root";print superuser}'
    root
    
    使用-v参数就没有上面的限制
    [root@centos7 ~]# awk -v superuser=root 'BEGIN{print superuser}'
    root
    

    6. ACTION

    6.1 printf命令:按照指定的FORMAT进行格式化输出;

    格式化输出:printf FORMAT, item1, item2, ...
    FORMAT:FORMAT是一个字符串, 它包含按字面打印的文本, 中间散布着格式说明符, 格式说明符用于说明如何打印值. 一个格式说明符是一个%, 后面跟着几个字符, 这些字符控制一个value 的输出格式. 第一个格式说明符说明item1 的输出格式, 第二个格式说明符说明item2 的输出格式, 依次类推. 于是, 格式说明符的数量应该和被打印的item 一样多;
    
    printf不会自动产生换行符,必须手动创建;
    

    格式符

    %s:显示字符串;
    %i,%d:显示十进制整数;
    

    修饰符

    #[.#]:第一个#控制显示的宽度,第二个#表示小数点后的精度;
    	例如:%3.1f
    -减号:左对齐(不加减号,默认为右对齐);
    +加号:显示数值的符号;
    

    实例

    例如:使用printf打印/etc/passwd中的$1和$3
    [Allen@centos7 ~]$ head /etc/passwd | awk -F: '{printf "Username: %-12sUID: %-8i
    ",$1,$3}'
    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       
    Username: halt        UID: 7       
    Username: mail        UID: 8       
    Username: operator    UID: 11       
    

    6.2 if-else

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

    实例

    例如:当$3大于等于1000时,打印$1;
    [Allen@centos7 ~]$ awk -F: '{if($3>=1000) printf "%s
    ",$1}' /etc/passwd
    Allen
    logstash
    
    例如:当$3大于等于1000时,打印为CommonUser: $1;否则打印为Systemuser: $1;
    [Allen@centos7 ~]$ awk -F: '{if($3>=1000) {printf "CommonUser: %-15s
    ",$1} else {printf "SystemUser: %s
    ",$1}}' /etc/passwd | head 
    SystemUser: root
    SystemUser: bin
    SystemUser: daemon
    SystemUser: adm
    SystemUser: lp
    SystemUser: sync
    SystemUser: shutdown
    SystemUser: halt
    SystemUser: mail
    SystemUser: operator
    

    6.3 while

    语法:while(condition){statements}
    使用场景:对一行内的多个字段逐一进行类似处理时使用;或对数组中的各元素逐一处理时使用;
    

    实例

    例如:以空格开头0次或多次,后跟linux16的行,以空格为分隔符,显示每行中各字段的长度;
    [Allen@centos7 ~]$ sudo awk '/^[[:space:]]*linux16/{i=1;while(i<=NF) {printf "%-55s%i
    ",$i,length($i); i++}}' /boot/grub2/grub.cfg
    linux16                                                7
    /vmlinuz-4.18.14-1.el7                                 22
    root=UUID=2073d1d0-1eab-4a58-900e-b9bfd178278f         46
    ro                                                     2
    rhgb                                                   4
    quiet                                                  5
    linux16                                                7
    /vmlinuz-3.10.0-693.el7.x86_64                         30
    root=UUID=2073d1d0-1eab-4a58-900e-b9bfd178278f         46
    ro                                                     2
    rhgb                                                   4
    quiet                                                  5
    
    例如:以空格开头0次或多次,后跟linux16的行,以空格为分隔符,只显示每行中字段的长度>=7的字段;
    [Allen@centos7 ~]$ sudo awk '/^[[:space:]]*linux16/{i=1;while(i<=NF) {if(length($i)>=7) {printf "%-55s%i
    ",$i,length($i)}; i++}}' /boot/grub2/grub.cfg
    linux16                                                7
    /vmlinuz-4.18.14-1.el7                                 22
    root=UUID=2073d1d0-1eab-4a58-900e-b9bfd178278f         46
    linux16                                                7
    /vmlinuz-3.10.0-693.el7.x86_64                         30
    root=UUID=2073d1d0-1eab-4a58-900e-b9bfd178278f         46
    

    6.4 for

    语法:for(expr1;expr2;expr3) statement
    特殊用法:for(var in arry) statements		##用于遍历数组中的元素
    

    实例

    例如:以空格开头0次或多次,后跟linux16的行,以空格为分隔符,显示每行中各字段的长度;
    [Allen@centos7 ~]$ sudo awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++) printf "%-55s%i
    ",$i,length($i)}' /etc/grub2.cfg 
    linux16                                                7
    /vmlinuz-4.18.14-1.el7                                 22
    root=UUID=2073d1d0-1eab-4a58-900e-b9bfd178278f         46
    ro                                                     2
    rhgb                                                   4
    quiet                                                  5
    linux16                                                7
    /vmlinuz-3.10.0-693.el7.x86_64                         30
    root=UUID=2073d1d0-1eab-4a58-900e-b9bfd178278f         46
    ro                                                     2
    rhgb                                                   4
    quiet                                                  5
    

    7. 描述awk函数示例(至少3例)

    length([s]):统计s的字符数量;
    sub(r,s):将当前行中最左边第一个能被r匹配的内容,替换成s;
    sub(r,s,t):将t中最左边第一个能被r匹配的内容,替换成s;
    gsub(r,s):将当前行中能被r匹配的内容,全部替换成s;
    gsub(r,s,t ):将t中能被r匹配的内容,全部替换成s;
    split(s,a):将s分割,然后分别加入到数组a中(awk命令中没有指定FS则使用默认的空格做为分隔符);
    split(s,a,fs):使用fs将s分割,然后分别加入到数组a中;
    sprintf(format,expr1,expr2,exprn):返回一个字符串(不打印),这个字符串按指定的format格式化expr1..exprn
    genline:读取下一行,重新设定NF、NR、FNR;

    实例

    实例1:length函数
    [root@centos7 ~]# awk 'BEGIN{superuser="root";print length(superuser)}'
    4
    
    实例2:sub和gsub函数
    [root@centos7 ~]# echo "hello World" | awk '{sub("l",1);print $0}'
    he1lo World
    [root@centos7 ~]# echo "hello World" | awk '{sub("l",1,$1);print $0}'
    he1lo World
    
    [root@centos7 ~]# echo "hello World" | awk '{gsub("l",1);print $0}'
    he11o Wor1d
    [root@centos7 ~]# echo "hello World" | awk '{gsub("l",1,$1);print $0}'
    he11o World
    
    实例3:split函数
    数组下标从1开始
    [root@centos7 ~]# awk -F/ 'BEGIN{i="China/America/Britain";split(i,countrys);for(c=1;c<=3;c++)print countrys[c]}'
    China
    America
    Britain
    [root@centos7 ~]# awk 'BEGIN{i="China/America/Britain";split(i,countrys,"/");for(c=1;c<=3;c++)print countrys[c]}'
    China
    America
    Britain
    
    实例4:sprintf函数
    [root@centos7 ~]# awk -F: 'NR>=1&&NR<=5{x=sprintf("%-10s%-5d",$1,$3);print x}' /etc/passwd
    root      0    
    bin       1    
    daemon    2    
    adm       3    
    lp        4  
    
    实例5:getline函数
    打印出从1到10之间的偶数
    awk首先读取到了第一行,就是1,然后getline,就得到了1下面的第二行,就是2,因为getline之后,awk会改变对应的NF,NR,FNR和$0等内部变量,所以此时的$0的值就不再是1,而是2了,然后将它打印出来。以此类推,就可以得到下面的结果。
    [Allen@centos7 ~]$ seq 10 | awk '{getline; print $0}'
    2
    4
    6
    8
    10
    
    打印出从1到10之间的奇数
    因为getline在print $0之后,此时的$0仍然是第一行。然后getline,$0变成了下一行2。依次类推,就打印出了奇数行。
    [Allen@centos7 ~]$ seq 10 | awk '{print $0; getline}'
    1
    3
    5
    7
    9
    
  • 相关阅读:
    Trie Tree和Radix Tree
    DataNode Layout升级解决Du操作引发的性能问题
    Write-Ahead Log(WAL)的工作原理
    YARN的共享存储服务
    AWS S3存储基于Hadoop之上的一致性保证
    简单聊聊HDFS RBF第二阶段工作近期的一些进展
    基于 Confluence 6 数据中心的 SAML 单点登录设置你的身份提供者
    基于 Confluence 6 数据中心的 SAML 单点登录设置 SSL/TLS
    Confluence 6 基于 Confluence 数据中心的 SAML 单点登录
    Confluence 6 用自带的用户管理
  • 原文地址:https://www.cnblogs.com/jzbgltb/p/9895397.html
Copyright © 2011-2022 走看看