信息
操作系统
Linux
开发语言
C/C++
开源协议
GPL
AWK
awk是一种编程语言,用于在linux/unix下对文本和数据进行处理。数据可以来自标准输入、一个或多个文件,或其它命令的输出。它支持用户自定义 函数和动态正则表达式等先进功能,是linux/unix下的一个强大编程工具。它在命令行中使用,但更多是作为脚本来使用。awk的处理文本和数据的方 式是这样的,它逐行扫描文件,从第一行到最后一行,寻找匹配的特定模式的行,并在这些行上进行你想要的操作。如果没有指定处理动作,则把匹配的行显示到标 准输出(屏幕),如果没有指定模式,则所有被操作所指定的行都被处理。awk分别代表其作者姓氏的第一个字母。因为它的作者是三个人,分别是Alfred Aho、Brian Kernighan、Peter Weinberger。gawk是awk的GNU版本,它提供了Bell实验室和GNU的一些扩展。
收起全文
精华内容
下载资源
问答
  • AWK

    千次阅读 多人点赞 2019-06-06 23:35:35
    一.AWK基本概念 1.基本用法 1.Centos中的文本处理工具 1)grep,egrep,fgrep:基于pattern(模式)的文本过滤工具 2)sed:流编辑器,行编辑器;通过模式空间,保持空间实现编辑 3)AWK:报告生成器,实现格式化...

    一.AWK基本概念

    1.基本用法

    1.Centos中的文本处理工具
    1)grep,egrep,fgrep:基于pattern(模式)的文本过滤工具

    2)sed:流编辑器,行编辑器;通过模式空间,保持空间实现编辑

    3)AWK:报告生成器,实现格式化文本输出

    gawk - pattern scanning and processing language:基于模式扫描以及语言处理
    1.AWK: Aho, Weinberger, Kernighan --> New AWK, NAWK
    2.现如今一般使用的是GNU awk,即为gawk
    awk实际为gawk的符号链接
    [root@sakura ~]# which awk 
    /usr/bin/awk
    [root@sakura ~]# ls -l /usr/bin/awk
    "lrwxrwxrwx. 1 root root 4 5月   6 16:16 /usr/bin/awk -> gawk"
    

    ps:gwak是一种过程式编程语言。gwak还支持条件判断,数组,循环等各种编程语言中所有可以使用的功能,因此可以将其称为一种脚本语言解释器。
    2.基本用法:gawk [options] 'program' FILE ...
    1)program:pattern{action statements}

    1.program:编程语言
    2.pattern:模式
    3.action statements:动作语句,可以由多个语句组成,各个语句间使用分号分隔;例如print;pringtf
    

    2)-F选项:指明输入时用到的字段分隔符

    3)-v var=value:自定义变量

    4)awk在处理文本时也是一次读取一行,根据分隔符来进行切片,将分割出来的每一片都保存在awk的内部变量中,其分别为$1,$2,$3…以此类推至最后一个变量

    3.print:print item1,item2,....;awk的输出命令之一
    1)1)item:字符串,用引号引用,并且各item之间需要使用,隔开;例如print “kasumi”,“world”

    [root@sakura ~]# awk -F: '{print $1,$3}' /etc/passwd 
    root 0
    bin 1
    daemon 2
    若各item间未使用,隔开,则会将$1$3连续输出
    [root@sakura ~]# awk -F: '{print $1 $3}' /etc/passwd
    root0
    bin1
    [root@sakura ~]# awk -F: '{print $1$3}' /etc/passwd
    root0
    bin1
    ps:其输出时默认的分隔符为空白字符
    
    

    2)输出的各item可以当字符串,也可以是数值;当前记录的字段,变量或awk的表达式;数值会被隐式转换为字符串进行输出

    字符串  item为字符串时需要使用" ",若将$1写入" "中,则不会引用awk内部变量
    [root@sakura ~]# awk -F: '{print "kasumi:",$1,$3}' /etc/passwd
    kasumi: root 0
    kasumi: bin 1
    [root@sakura ~]# awk -F: '{print "kasumi:$1"}' /etc/passwd
    kasumi:$1
    数值   item为数值时不需要" "
    [root@sakura ~]# awk -F: '{print 516,$1,$3}' /etc/passwd
    516 root 0
    516 bin 1
    当前记录的字段
    [root@sakura ~]# awk -F: '{print $1,$7}' /etc/passwd
    root /bin/bash
    bin /sbin/nologin
    变量   ietm为变量时不需要使用$
    [root@sakura ~]# awk -v path=kasumi 'BEGIN{print path}'
    kasumi
    

    3)如果省略item,则相当于$0,即输出整行

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

    4)输出空白字符:print “”

    [root@sakura ~]# tail -2 /etc/passwd | awk '{print ""}'
    
    ps:其表示为每处理一行信息,就输出空白字符
    

    4.awk内建变量
    1)FS:input field seperator,输入字段分隔符,与-F选项作用相同,默认为空白字符

    [root@sakura ~]# awk -v FS=":" '{print $1,$3}' /etc/passwd
    root 0
    bin 1
    

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

    [root@sakura ~]# awk -v FS=":" -v OFS=":" '{print $1,$3}' /etc/passwd
    root:0
    bin:1
    

    3)RS:input record seperator,输入时得换行符,默认为\n换行符

    [root@sakura ~]# awk -v RS=":" '{print}' /etc/passwd
    root
    x
    0
    0
    ps:文本本身自带的\n换行符也会启换行作用
    

    4)ORS:utput record seperator,输出时的换行符,默认为\n换行符

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

    5)NF:number of field,字段数量

    1.NF  每行按分隔符计量的字段数
    [root@sakura ~]# awk  -F" "  '{print NF}' /etc/fstab 
    0
    1
    2
    2.$NF  表示仅显示每行最后一个字段,NF会被替换为每行的字段数量
    [root@sakura ~]# awk  -F" "  '{print $NF}' /etc/fstab 
    
    #
    /etc/fstab
    2019
    

    6)NR:number of record,统计行数,即给每行显示行数;命令后跟的所有文件将统一合并计数

    [root@sakura ~]# awk '{print NR}' /etc/fstab /etc/issue
    1
    2
    3
    ps:若命令后跟多个文件,其行数不会分别显示
    

    7)FNR:各文件分别计数;行数

    [root@sakura ~]# awk '{print FNR}' /etc/fstab /etc/issue
    

    8)FILENAME:当前文件名

    [root@sakura ~]# awk '{print FILENAME}' /etc/issue
    /etc/issue
    /etc/issue
    /etc/issue
    [root@sakura ~]# awk 'FNR==1{print FILENAME}' /etc/issue /etc/fstab 
    /etc/issue
    /etc/fstab
    ps:需要注意,指定文件有多少行,就会显示多少行文件名,使用操作符FNR==1可仅显示一行文件名
    

    9)ARGC:命令行参数的个数

    [root@sakura ~]# awk '{print ARGC}' /etc/fstab  /etc/issue
    3
    

    10)ARGV:表示数组,保存的是命令行所给定的各个参数

    [root@sakura ~]# awk 'NR==1{print ARGV[0]}' /etc/fstab  /etc/issue
    awk
    [root@sakura ~]# awk 'NR==1{print ARGV[1]}' /etc/fstab  /etc/issue
    /etc/fstab
    [root@sakura ~]# awk 'NR==1{print ARGV[2]}' /etc/fstab  /etc/issue
    /etc/issue
    ps:程序段不会记录于其数组中
    

    5.aw自定义变量
    1)使用选项定义变量;-v var=value;变量名区分字符大小写

    [root@sakura ~]# awk -v stars=yuki '{print stars}' /etc/issue
    yuki
    yuki
    yuki
    ps:这里文件内容未起作用,但是使用了文件的行数
    

    2)在program中直接定义变量

    [root@sakura ~]# awk 'BEGIN{FS=":";f1=3}{print $f1}' /etc/passwd
    0
    1
    [root@sakura ~]# awk 'BEGIN{stars="yuki";print stars}'
    yuki
    

    6.printf格式化输出命令:awk的输出命令之二
    1)语法:printf FORMAT, item1, item2, …

    1.FORMAT必须要给出
    2.printf不会自动实现换行,需要显示给出换行控制符,\n
    3.FORMAT中需要分别为后面的每个item指定一个格式化符号
    

    2)格式符对照表

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

    3)修饰符

    1.#[.#]:第一个数字控制显示的宽度;第二个#表示小数点后的精度;例如,%3.1f,显示为浮点数
    2.-:表示左对齐
    3.+:显示数值的符号
    ps:默认为右对齐
    

    4)练习

    使用printf控制符
    [root@sakura ~]# awk -F: '{printf "usernmae:%s,UID:%d\n",$1,$3}' /etc/passwd
    usernmae:root,UID:0
    usernmae:bin,UID:1
    usernmae:daemon,UID:2
    ps:运行时会将$1,$3分别对应至%s,%d上
    
    使用printf修饰符
    [root@sakura ~]# awk -F: '{printf "usernmae: %-15s,UID: %d\n",$1,$3}' /etc/passwd
    usernmae: root           ,UID: 0
    usernmae: bin            ,UID: 1
    %-15s表示为,左对齐,%s的宽度为15
    

    7.操作符
    1)算术操作符:

    1.x+y, x-y, x*y, x/y, x^y, x%y
    2.-x:转换为负数
    3.+x:将字符串转换为数值
    

    2)字符串操作符:没有符号的操作符,表示为字符串连接

    3)赋值操作符

    1.=, +=, -=, *=, /=, %=, ^=
    2.++, --
    

    4)比较操作符

    >, >=, <, <=, !=, ==
    

    5)模式匹配符

    1.~:是否被模式所匹配
    2.!~:是否被模式不匹配
    

    6)逻辑操作符

    1.&&
    2.||
    3.!
    

    7)函数调用

    function_name(argu1,argu2,....)
    

    8)条件表达式

    selector?if-true-expression:if-false-expression
    

    9)练习判断/etc/passwd文件中每个用户的UID,若其大于1000则显示common user,否则显示sysuser or sysadmin

    [root@sakura ~]# awk -F: '{$3>=1000?usertype="common user":usertype="sysuser or sysadmin";printf "%15s:%-s\n",$1,usertype}' /etc/passwd
               root:sysuser or sysadmin
                bin:sysuser or sysadmin
             daemon:sysuser or sysadmin
    

    8.PATTERN:模式
    1)empty:空模式,匹配所有行

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

    [root@sakura ~]# awk '/^UUID/{print $1}' /etc/fstab 
    UUID=366bd0a8-f2cc-4cc6-beaa-418dacdae36f
    UUID=274b447f-b701-439b-908a-f328de77cf63
    UUID=f9fc6d2d-a8d1-4f08-9aba-8999f3da565c
    UUID=362e5f41-bc95-46ff-9902-d4e5c634ad99
    [root@sakura ~]# awk '!/^UUID/{print $1}' /etc/fstab 
    
    #
    #
    [root@sakura ~]# awk -F: '/^[ab]/{print $1,$3}' /etc/passwd
    bin 1
    adm 3
    abrt 173
    

    3)relational expression 关系表达式:结果有“真”或“假”;结果为“真”才会被处理;
    结果为非0数值或非空字符串,即可认为是"真"

    [root@sakura ~]# awk -F: '$3>=1000{print $1,$3}' /etc/passwd
    nfsnobody 65534
    yuki 1000
    tom 1001
    [root@sakura ~]# awk -F: '$1~/root/{print $1,$3}' /etc/passwd
    root 0
    [root@sakura ~]# awk -F: '$NF=="/bin/bash"{print $1,$NF}' /etc/passwd
    root /bin/bash
    yuki /bin/bash
    [root@sakura ~]# awk -F: '$NF~/bash$/{print $1,$NF}' /etc/passwd
    root /bin/bash
    yuki /bin/bash
    tom /bin/bash
    

    4)line ranges:行范围

    1.startlin,endline:/part1/,/part2/
    [root@sakura ~]# awk -F: '/^root/,/^adm/{print $1}' /etc/passwd
    root
    bin
    daemon
    adm
    2.基于行数判断
    [root@sakura ~]# awk -F: '(NR>=1&&NR<=5){print $1}' /etc/passwd
    root
    bin
    daemon
    adm
    lp
    ps:不支持直接给出数字的格式
    

    5)BEGIN/END模式

    1.BEGIN{}:仅在开始处理文件中的文本之前执行一次
    2.END{}:仅在文本处理完成之后执行一次
    [root@sakura ~]# awk -F: 'BEGIN{print "   username    uid  \n-----------------"}{printf "%-10s %10d\n",$1,$3}END{print "===========\n    end    "}' /etc/passwd
       username    uid  
    -----------------
    root                0
    bin                 1
    daemon              2
    .
    .
    .
    abc8             1013
    abc9             1014
    abc10            1015
    ===========
        end    
    

    9.常用的action

    1.Expressions(表达式)
    2.Control statements:if, while等
    3.Compound statements:组合语句(将多个语句当做当个代码块运行,多个语句需要使用{})
    4.input statements
    5.output statements
    

    二.控制语句

    1.常用控制语句格式

    1.if(条件:condition) {条件为真时语句:statments} 
    2.if(condition) {statments} else {statements} (双分支语句,组合语句中若有一个以上语句需要使用{},否则可以省略{})
    3.while(conditon) {statments}
    4.do {statements} while(condition)  (不论条件是否为真,都先循环一次循环体)
    5.for(expr1;expr2;expr3) {statements}
    6.break
    7.continue
    8.delete array[index] (从数组中删除指定语句)
    9.delete array
    10.exit  (退出语句)
    11.{ statements }
    

    2.if-else语句:if(condition) {statement} else {statement}
    1)判断/etc/passwd文件中每个用户的UID,若其大于1000则显示common user,否则显示sysuser or sysadmin

    print打印
    [root@sakura ~]# awk -F: '{if($3>=1000){print "common user:",$1,$3}else{print "sysuser or sysadmin:",$1,$3}}' /etc/passwd
    sysuser or sysadmin: root 0
    sysuser or sysadmin: bin 1
    common user: abc9 1014
    common user: abc10 1015
    printf打印
    [root@sakura ~]# awk -F: '{if($3>=1000){printf "common user: %s,%d\n",$1,$3}else{printf "sysuser or sysadmin: %s,%d\n",$1,$3}}' /etc/passwd
    sysuser or sysadmin: root,0
    sysuser or sysadmin: bin,1
    sysuser or sysadmin: daemon,2
    common user: abc9,1014
    common user: abc10,1015
    

    2)判断/etc/passwd文件中每个用户的的bash是否为/bin/bash,并输出

    [root@sakura ~]# awk -F: '{if($NF=="/bin/bash"){print $1,$NF}}' /etc/passwd
    root /bin/bash
    yuki /bin/bash
    tom /bin/bash
    

    3)判断/etc/fstab文件中每行的字段是否大于5,大于5的话则输出整行

    [root@sakura ~]# awk '{if(NF>=5){print $0}}' /etc/fstab 
    # Created by anaconda on Mon May  6 16:16:15 2019
    # Accessible filesystems, by reference, are maintained under '/dev/disk'
    

    4)判断df -h命令显示的文件系统用量中,已用量超过20%的分区,并显示之

    [root@sakura ~]# df -h | awk -F% '/^\/dev/{print $1}' | awk '{if($NF>=20){print $1,$NF}}'
    /dev/sda3 44
    /dev/sda2 26
    

    ps:使用场景为,对awk取得的 整行或某个字段做条件判断

    3.while循环:while(condition){statement};条件为真时进入循环,条件为假时,退出循环
    1)判断/etc/grub2.cfg中,linux16开头的行中的每个单词的字符数

    [root@sakura ~]# awk '/^[[:space:]]*linux16/{i=1;while(i<=NF){print $i,length($i);i++}}' /etc/grub2.cfg 
    linux16 7
    /vmlinuz-3.10.673.10.67.2-el7 29
    root=UUID=366bd0a8-f2cc-4cc6-beaa-418dacdae36f 46
    ro 2
    

    2)判断/etc/grub2.cfg中,显示linux16开头的行中的每个单词的字符数大于等于7的单词

    [root@sakura ~]# awk '/^[[:space:]]*linux16/{i=1;while(i<=NF){if(length($i)>=7){print $i,length($i)};i++}}' /etc/grub2.cfg 
    linux16 7
    /vmlinuz-3.10.673.10.67.2-el7 29
    root=UUID=366bd0a8-f2cc-4cc6-beaa-418dacdae36f 46
    crashkernel=auto 16
    LANG=en_US.UTF-8 16
    linux16 7
    

    3)列出/etc/grub2.cfg文件中,当前系统可使用的内核,并对其编号

    [root@sakura ~]# awk -F\' '/^menuentry/{print i++":",$2}' /etc/grub2.cfg 
    0: CentOS Linux (3.10.673.10.67.2-el7) 7 (Core)
    1: CentOS Linux (3.10.67linux-3.10.67-1-el7) 7 (Core)
    2: CentOS Linux (3.10.0-693.el7.x86_64) 7 (Core)
    3: CentOS Linux (0-rescue-114408c9377741bc91b9e27df3c651f0) 7 (Core)
    

    ps:对一行内的多个字段逐一做类似处理时使用;对数组中的各元素逐一处理时使用
    4.do-while循环:do {statement}while{condition}
    1)意义为:在进入while循环前,至少运行一次循环体

    5.for循环:for(expr1;expr2;expr3){statement}
    1)语法:for(variable assignment;condition;iteration process) {for-body}

    2)判断/etc/grub2.cfg中,linux16开头的行中的每个单词的字符数

    [root@sakura ~]# awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++){print $i,length($i)}}' /etc/grub2.cfg 
    linux16 7
    /vmlinuz-3.10.673.10.67.2-el7 29
    root=UUID=366bd0a8-f2cc-4cc6-beaa-418dacdae36f 46
    ro 2
    crashkernel=auto 16
    

    3)特殊用法:能够实现遍历数组中的元素

    语法:for(var in array){for-body}
    

    6.switch语句(类似bash shell中的case语句)
    1)语法:switch(expression){case VALUE1 or /REGEXP/:statement;case VALUE2 or /REGEXP/:statement;…;default:statement}
    ps:VALUE1 or /REGEXP为变量值或正则表达式能匹配到的内容;default为当所有选项不匹配时,显示的结构

    7.break和continue
    1)break [n]:可跳出n层循环
    2)continue:提前结束本轮循环,进入下轮循环

    8.next:跳出awk的内置循环,即提前结束对本行的处理而直接进入下一行
    1)输出/etc/passwd文件中用户ID为偶数的用户,使用next实现

    [root@sakura ~]# awk -F: '{if($3%2!=0){next}else{print $1,$3}}' /etc/passwd
    root 0
    daemon 2
    lp 4
    shutdown 6
    mail 8
    ps:使用awk -F: '{if($3%2!=0)next;print $1,$3}' /etc/passwd也可以实现
    

    三.array数组

    1.awk中一般使用关联数组:array[index-expression]
    1)index-expression,数组索引

    1.可使用任意字符串;字符串需要使用双引号
    2.如果某数组元素实现不存在,在引用时,awk会自动创建此元素,并将其值初始化为“空串”
    3.若需要判断数组中某元素是否存在,需要使用"index in array"格式进行,不能直接判断数组中的元素是否为空
    [root@sakura ~]# awk 'BEGIN{role["riben"]="kasumi";role["china"]="wanglin";print role["riben"]}'
    kasumi
    [root@sakura ~]# awk 'BEGIN{role["riben"]="kasumi";role["china"]="wanglin";print role["china"]}'
    wanglin
    

    2.若需要遍历数组中的每个元素,需要使用for循环
    1)for(var in array){for-body}

    [root@sakura ~]# awk 'BEGIN{role["riben"]="kasumi";role["china"]="wanglin";for(i in role){print role[i]}}'
    kasumi
    wanglin
    [root@sakura ~]# awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";for(i in weekdays) {print weekdays[i]}}'
    Tuesday
    Monday
    ps:var会遍历array的每一个索引
    

    2)统计netstat -tan命令中tcp协议各个状态的出现次数

    [root@sakura ~]# netstat -tan | awk '/^tcp\>/{stat[$NF]++}END{for(i in stat){print i,stat[i]}}'
    LISTEN 5
    ESTABLISHED 3
    

    3)统计/var/log/httpd/access_log文件中,各个ip访问的次数

    [root@sakura ~]# awk '{ip[$1]++}END{for(i in ip){print i,ip[i]}}' /var/log/httpd/access_log 
    192.168.3.19 72
    

    4)统计/etc/fstab文件中每个文件系统类型出现的次数

    [root@sakura ~]# awk '/^UUID/{fs[$3]++}END{for(i in fs){print i,fs[i]}}' /etc/fstab 
    swap 1
    xfs 3
    

    5)统计指定文件中每个单词出现的次数

    [root@sakura ~]# awk '{for(i=1;i<=NF;i++){count[$i]++}}END{for(i in count){print i,count[i]}}' /etc/fstab 
    man 1
    May 1
    and/or 1
    maintained 1
    xfs 3
    file 1
    

    四.awk内置函数

    1.数值处理:rand():返回0和1之间一个随机数

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

    2.字符串处理
    1)length([s]):返回指定字符串的长度
    2)sub(r,s,[t]):以r表示的模式来查找t所表示的字符中的匹配的内容,并将其第一次出现替换为s所表示的内容

    [root@sakura ~]# awk -F: '{print sub(o,O,$1)}' /etc/passwd
    1
    1
    1
    ps:显示结果为显示是否替换成功
    

    3)gsubsub(r,s,[t]):以r表示的模式来查找t所表示的字符中的匹配的内容,并将其所有出现均替换为s所表示的内容
    4)split(s,a,[r]):以r为分隔符切割字符s,并将切割后的结果保存至a所表示的数组中

    统计客户端访问http服务的次数
    [root@sakura ~]# netstat -tan | awk '/^tcp\>/{split($5,ip,":");count[ip[1]]++}END{for(i in count){print i,count[i]}}'
    192.168.3.19 3
    0.0.0.0 5
    

    ps:awk也可使用自定义函数

    展开全文
  • awk

    千次阅读 2018-04-28 06:17:03
    awkawk兼具sed的所有功能,而且还支持分段截取文档中某个段打印文档中的某段,-F作用是指定分隔符打印所有的段awk -F ':' '{print $0}' 1.txt打印文件的全部内容awk '{print $0}' 1.txt,不需要加F,类似于cat查看...

    awk

    awk兼具sed的所有功能,而且还支持分段


    截取文档中某个段

    打印文档中的某段,-F作用是指定分隔符


    打印所有的段awk -F ':' '{print $0}' 1.txt


    打印文件的全部内容awk  '{print $0}' 1.txt,不需要加F,类似于cat查看文件


    awk如果不指定分隔符,则默认空格或空白为分隔符


    打印多段内容awk -F ':' '{print $1,$2,$4}' 1.txt


    打印内容可以指定#来分割,需要用到双引号


    awk匹配功能

    awk '/oo/' 1.txt ,匹配包含oo的行




    awk -F ':' '$1 ~ /oo/' 1.txt ,打印第一段中包含oo的行,~表示匹配


    awk -F ':' '$1 ~ /o+/' test.txt ,匹配第一段中包含o的行,支持正则表达式;这里需要知道,出现特殊符号时,awk不用加脱义字符,grep和sed则必须要加脱义字符


    awk支持多个表达式一起写




    针对数学表达式的用法

    awk -F ':' '$3==0' 1.txt ,匹配第3段等于0的;

    awk -F ':' '$3==0 {print $1}' 1.txt //匹配第3段等于0的,并打印第1段;

    awk -F ':' '$3>=1000' 1.txt //匹配第3段大于等于1000的,并打印所有段


    awk -F ':' '$3>="1000"' 1.txt,“1000”是以ASC码值进行排序的,被认为是字符串


    awk -F ':' '$7!="/sbin/nologin" {print $0}' 1.txt ,匹配出第7段不是/sbin/nologin的所有段,!=表示不匹配



    条件操作符

    awk -F ':' '$3<$4' 1.txt ,匹配比较第3段小于第4段的行;awk -F ':' '$3==$4' 1.txt,匹配出第3段和第4段相等的行,==就是等于,精确匹配


    awk -F ':' '$3>"5" && $3<"7"' 1.txt ,匹配第3段大于5的,和小于7的行,&&表示并且的意思


    awk -F ':' '$3>1000 || $7=="/sbin/nologin"' 1.txt ,匹配第3段大于1000的,或者第7段等于/sbin/nologin的所在的行,|| 表示 或者 的意思


    awk -F ':' '$3>1000 || $7 ~ /bash/' 1.txt,匹配第3段大于1000的,或者第7段包含/bash/的



    awk的内置变量

    常用的变量有OFS、NF和NR,OFS与-F选项有类似的功能,用来定义分隔符,但是在输出时定义

    awk -F ':' '{OFS="#"} {if ($3>1000) {print $1,$3,$7}}' 1.txt //匹配第3段大于1000,第7段匹配/bash/的,然后打印第1,第3,第7段内容, 并用#分割


    NF表示用分隔符分割后一共有多少行;NR表示行号



    awk -F ':' 'NR<=10' 1.txt ,打印前10行;awk -F ':' 'NR<=10 && $1 ~ /root|sync' 1.txt,匹配前10行中,第1段包含root或者sync的


    awk -F ':' 'NF==6 && $1 ~ /root|sync/' 1.txt,匹配文件中是6段的,并在第1段包含root或者sync的


    awk -F ':' '{print $NR":"$NF}' 1.txt


    head -n3 1.txt |awk -F ':' '$1="root"' ,在前3行中,给第1段赋值为root


    awk -F ':' '{(tot=tot+$3)}; END {print tot}' 1.txt,tot值求和,tot默认0开始,每次和新的第三段值相加,最终第三段值加完,输出tot值


    扩展

    练习题






























    展开全文
  • awk

    千次阅读 2011-03-02 13:20:00
    @roylez: bizarrely trapped详解著名的awk oneliner,第一部分:空行、行号和计算偶然在网上看到有人注释过的《awk oneliner》,而且注释的人声称“全部弄懂这 些就已经是awk高手了”,而我也一直想学下awk又懒得花...

    cat b_noshp.bat | gawk 'NF {print;print "echo -----",NR,NR,NR;}' > b_noshp_log.bat 

     

    详解著名的awk oneliner,第一部分:空行、行号和计算

    偶然在网上看到有人注释过的《awk oneliner》,而且注释的人声称“全部弄懂这 些就已经是awk高手了”,而我也一直想学下awk又懒得花时间,然后就觉得这个东 西一定很适合我。为了督促自己看完这个系列,决定整个给翻译一遍。说实话看了 第一篇之后觉得awk的语句也不是那么天书了。原作者是Peteris Krumins,一个很 酷的家伙,你可以在titter上follow他(Peteris Krumins)。

    原文请见:http://www.catonmat.net/blog/awk-one-liners-explained-part-one/

    将每行后面都添加一个空行

    awk '1; { print "" }'
    

    这是怎么意思呢?一个单行awk命令,其实也是一个用awk语言写的程序,每个awk程序,都是由一系列的“匹配模式 { 执行动作 }”语句所组成的。在这个例子里面,有两个语句,“1”和“{print ""}”。在每个“匹配模式——执行动作”语句中,模式和动作都是可以被省略的。如果匹配模式被省略,那么预定的动作将会对输入文件的每一行执行。如果动作被省略,那么就默认会执行{print }。所以,这个单行awk语句等同于下面的语句

    awk '1 {print } {print ""}'
    

    动作只有在匹配模式的值为真的时候才会执行。因为“1”永远为真,所以,这个例子也可以写成下面的形式

    awk '{print } {print ""}'
    

    awk中每条print语句后都默认会输出一个ORS变量(Output Record Separator,即输出行分隔符,默认为换行符)。第一个不带参数的print语句,等同于print $0,其中$0是代表整行内容的变量。第二个print语句什么也不输出,但是鉴于print语句后都会被自动加上ORS变量,这句的作用就是输出一个新行。于是每行后面加空行的目的就达到了。

    添加空行的另一种方法

    awk 'BEGIN { ORS="/n/n" }; 1'
    

    BEGIN是一个特殊的模式,后面所接的内容,会在文件被读入前执行。这里,对ORS变量进行了重新定义,将一个换行符改成了两个。后面的“1”,同样等价于{print },这样就达到了在每行后用新的ORS添加空行的目的。

    在每个非空的行后面添加空行

    awk 'NF {print $0 "/n"}'
    

    这个语句里面用到了一个新的变量,NF(number of fields),即本行被分割成的字段的数目。例如,“this is a test”,会被awk分割成4个词语,NF的值就为4。当遇到空行,分割后的字段数为0,NF为0,后面的匹配动作就不会被执行。这条语句,可以理解成“如果这一行可以分割成任意大于0的部分,那么输出当前行以及一个换行符”。

    在每行后添加两个空行

    awk '1; {print "/n"}'
    

    这一语句与前面的很相似。“1”可以理解为{print },所以整个句子可以改写为

    awk '{print ; print "/n"}'
    

    它首先输出当前行,然后再输出一个换行符以及一个结束print语句的ORS,也就是另外一个换行符。

    为每个文件的内容添加行号

    awk '{ print FNR "/t" $0 }'
    

    这个awk程序在每行的内容前添加了一个变量FNR的输出,并用一个制表符进行分隔。FNR(File Number of Row)这个变量记录了当前行在当前文件中的行数。在处理下一个文件时,这个变量会被重置为0。

    为所有文件的所有行统一添加行号

    awk '{print NR "/t" $0}'
    

    这一句与上一例基本一样,除了使用的行号变量是NR(Number of Row),这个变量不会在处理新文件的时候被重置。所以说,如果你有2个文件,一个10行一个12行,那这个变量会从1一直变到22。

    用更漂亮的样式添加行号

    awk '{printf("%5d : %s/n", FNR, $0)}'
    

    这个例子用了printf函数来自定义输出样式,它所接受的参数与标准C语言的printf函数基本一致。需要注意的是,printf后不会被自动添加ORS,所以你需要自己指定换行。这个语句指定了行号会右对齐,然后是一个空格和冒号,接着是当前行的内容。

    为文件中的非空行添加行号

    awk 'NF { $0=++a " :" $0}; {print }'
    

    Awk的变量都是自动定义的:你第一次用到某个变量的时候它就自动被定义了。这个语句在每次遇到一个非空行的时候先把一个变量a加1,然后把a的数值添加到行首,然后输出当前行的内容。

    计算文件行数(模拟 wc -l)

    awk 'END {print NR}'
    

    END是另外一个不会被检验是否为真的模式,后面的动作会在整个文件被读完后进行。这里是输出最终的行号,即文件的总行数。

    对每行求和

    awk '{s=0;for (i=0;i<NF;i++) s=s+$i; print s}'
    

    Awk有些类似C语言的语法,比如这里的for (;;;){ ... }循环。这句命令会让程序遍历所有NF个字段,并把字段的总和存在变量s中,最后输出s的数值并处理下一行。

    对所有行所有字段求和

    awk '{for (i=0;i<NF;i++) s=s+$i; END {print s+0}'
    

    这个例子与上一个基本一致,除了输出的是所有行所有字段的和。由于变量会被自动定义,s只需要定义一次,故而不需要把s定义成0。另外需要注意的是,它输出{print s+0}而非{print s},这是因为如果文件为空,s不会被定义就不会有任何输出了,输出s+0可以保证在这种情况下也会输出更有意义的0。

    将所有字段替换为其绝对值

    awk '{ for (i = 1; i <= NF; i++) if ($i < 0) $i = -$i; print }'
    

    这条语句用了C语言的另外两个特性,一个是if (...) {...}结构,另外就是省略了大括号。它检查对每一行,检查每个字段的值是否小于0,如果值小于0,则将其改为正数。字段名可以间接地用变量的形式引用,如i=5;$i='hello'会将第5个字段的内容置为hello。

    下面的是将这条语句完整的写出来的形式。print语句会在行中所有字段被改为正数后执行。

    awk '{
      for (i = 1; i <= NF; i++) {
        if ($i < 0) {
          $i = -$i;
        }
      }
      print
    }'
    

    计算文件中的总字段(单词)数

    awk '{total=total+NF};END {print total+0}'
    

    这个命令匹配所有的行,并不断的把行中的字段数累加到变量total。执行完成上述动作后,输出total的数值。

    输出含有单词Beth的行的数目

    awk '/Beth/ {n++}; END {print n+0}'
    

    这个例子含有两个语句。第一句找出匹配/Beth/的行,并对变量n进行累加。在/.../之间的内容为正则表达式,/Beth/匹配所有含有“Beth”的单词(它不仅匹配Beth,同样也匹配Bethe)。第二句在文件处理完成后输出n的数值。这里用n+0是为了让n为0 的情况下输出0而不是一个空行。

    寻找第一个字段为数字且最大的行

    awk '$1 > max { max=$1; maxline=$0 }; END { print max, maxline }'
    

    这个例子用变量max记录第一个字段的最大值,并把第一个字段最大的行的内容存在变量maxline中。在循环终止后,输出max和maxline的内容。注意:如果在数字都为负数的情况下,这个例子就不能用了,下面的是修改过的版本

    awk 'NR == 1 { max = $1; maxline = $0; next; } $1 > max { max=$1; maxline=$0 }; END { print max, maxline }'
    

    在每一行前添加输出该行的字段数

    awk '{print NF ":" $0}'
    

    这个例子仅仅是在逐行输出字段数NF,一个冒号,以及该行的内容。

    输出每行的最后一个字段

    awk '{print $NF}'
    

    awk里面的字段可以用变量的形式引用。这一句输出第NF个字段的内容,而NF就是该行的字段数。

    打印最后一行的最后一个字段

    awk '{ field = $NF };END {print field}'
    

    这个例子用field记录最后一个字段的内容,并在循环后输出field的内容。

    这里是一个更好的版本。它更常用、更简洁也更高效:

    awk 'END {print $NF}'
    

    输出所有字段数大于4的行

    awk 'NF > 4'
    

    这个例子省略了要执行的动作。如前所述,省略动作等价于{print}

    输出所有最后一个字段大于4的行

    awk '$NF > 4'
    

    这个例子用$NF引用最后一个字段,如果它的数值大于4,那么就输出。

     

    展开全文

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 231,044
精华内容 92,417
关键字:

awk