• awk教程


    AWK是一种处理文本文件的语言,是一个强大的文本分析工具。

    之所以叫AWK是因为其取了三位创始人 Alfred Aho,Peter Weinberger, 和 Brian Kernighan 的 Family Name 的首字符。

    一、awk的基本用法

    # 格式
    $ awk 动作 文件名
    
    # 示例
    $ awk '{print $0}' demo.txt

    print是打印命令,$0表示当前行

    [root@Server-n93yom ~]# echo 'this is a test' | awk '{print $0}'
    this is a test

    上面使用管道命令,输出的就是 this is test

    awk会根据空格和制表符,将每一行分成若干字段,依次用$1$2$3代表第一个字段、第二个字段、第三个字段等等。

    变量NF表示当前行有多少个字段,因此$NF就代表最后一个字段。

    [root@Server-n93yom ~]# echo 'this is a test' | awk '{print $4}'
    test
    [root@Server-n93yom tmp]# echo 'this is test' | awk '{print $NF}'
    test

    我们以/etc/passwd文件为例,用-F来指定分隔符为冒号,然后取第一个字段,则可以执行以下命令

    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
    halt:x:7:0:halt:/sbin:/sbin/halt
    mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
    operator:x:11:0:operator:/root:/sbin/nologin
    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-bus-proxy:x:999:997:systemd Bus Proxy:/:/sbin/nologin
    systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
    dbus:x:81:81:System message bus:/:/sbin/nologin
    polkitd:x:998:996:User for polkitd:/:/sbin/nologin
    tss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin
    postfix:x:89:89::/var/spool/postfix:/sbin/nologin
    sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
    check:x:1000:1000:check:/home/check:/bin/bash
    cfyuser:x:10000:10000::/home/cfyuser:/bin/bash
    consul:x:10002:10002::/opt/cloudchef/consul:/sbin/nologin
    rabbitmq:x:10003:10003::/etc/rabbitmq:/sbin/nologin
    mysql:x:10009:10009::/home/mysql:/bin/bash
    prometheus:x:10004:10004::/home/prometheus:/sbin/nologin
    grafana:x:10005:10005::/home/grafana:/bin/bash
    logstash:x:10006:10006::/home/logstash:/bin/bash
    nginx:x:997:995:nginx user:/var/cache/nginx:/sbin/nologin
    tomcat:x:10008:10008::/opt/cloudchef/tomcat:/sbin/nologin
    test:x:10010:10010::/home/test:/bin/bash
    test1:x:10011:10011::/home/test1:/bin/bash
    View Code
    [root@Server-n93yom tmp]# awk -F ':' '{print $1}' passwd
    root
    bin
    daemon
    adm
    lp
    sync
    shutdown
    halt
    mail
    operator
    games
    ftp
    nobody
    systemd-bus-proxy
    systemd-network
    dbus
    polkitd
    tss
    postfix
    sshd
    check
    cfyuser
    consul
    rabbitmq
    mysql
    prometheus
    grafana
    logstash
    nginx
    tomcat
    test
    test1

    二、变量

    $(NF-1)代表倒数第二个字段。

    [root@Server-n93yom tmp]# awk -F ':' '{print $1,$(NF-1)}' passwd
    root /root
    bin /bin
    daemon /sbin
    adm /var/adm
    lp /var/spool/lpd
    sync /sbin
    shutdown /sbin
    halt /sbin
    mail /var/spool/mail
    operator /root
    games /usr/games
    ftp /var/ftp
    nobody /
    systemd-bus-proxy /
    systemd-network /
    dbus /
    polkitd /
    tss /dev/null
    postfix /var/spool/postfix
    sshd /var/empty/sshd
    check /home/check
    cfyuser /home/cfyuser
    consul /opt/cloudchef/consul
    rabbitmq /etc/rabbitmq
    mysql /home/mysql
    prometheus /home/prometheus
    grafana /home/grafana
    logstash /home/logstash
    nginx /var/cache/nginx
    tomcat /opt/cloudchef/tomcat
    test /home/test
    test1 /home/test1

    上面代码中,print命令里面的逗号,表示输出的时候,两个部分之间使用空格分隔。

    NR表示当前处理的第几行 

    [root@Server-n93yom tmp]# awk -F ':' '{print NR ")" $(NF-1)}' passwd
    1)/root
    2)/bin
    3)/sbin
    4)/var/adm
    5)/var/spool/lpd
    6)/sbin
    7)/sbin
    8)/sbin
    9)/var/spool/mail
    10)/root
    11)/usr/games
    12)/var/ftp

    其他的一些内置变量

    变量描述
    $n 当前记录的第n个字段,字段间由FS分隔
    $0 完整的输入记录
    ARGC 命令行参数的数目
    ARGIND 命令行中当前文件的位置(从0开始算)
    ARGV 包含命令行参数的数组
    CONVFMT 数字转换格式(默认值为%.6g)ENVIRON环境变量关联数组
    ERRNO 最后一个系统错误的描述
    FIELDWIDTHS 字段宽度列表(用空格键分隔)
    FILENAME 当前文件名
    FNR 各文件分别计数的行号
    FS 字段分隔符(默认是任何空格)
    IGNORECASE 如果为真,则进行忽略大小写的匹配
    NF 一条记录的字段的数目
    NR 已经读出的记录数,就是行号,从1开始
    OFMT 数字的输出格式(默认值是%.6g)
    OFS 输出记录分隔符(输出换行符),输出时用指定的符号代替换行符
    ORS 输出记录分隔符(默认值是一个换行符)
    RLENGTH 由match函数所匹配的字符串的长度
    RS 记录分隔符(默认是一个换行符)
    RSTART 由match函数所匹配的字符串的第一个位置
    SUBSEP 数组下标分隔符(默认值是/034)

    三、函数

    toupper表示把字段变为大写

    [root@Server-n93yom tmp]# awk -F ':' '{print NR ")" toupper($1)}' passwd
    1)ROOT
    2)BIN
    3)DAEMON
    4)ADM
    5)LP
    6)SYNC
    7)SHUTDOWN
    8)HALT
    9)MAIL
    10)OPERATOR
    11)GAMES
    12)FTP
    13)NOBODY
    14)SYSTEMD-BUS-PROXY
    15)SYSTEMD-NETWORK
    16)DBUS

    其他的内置函数如下

    tolower():字符转为小写。
    length():返回字符串长度。
    substr():返回子字符串。
    sin():正弦。
    cos():余弦。
    sqrt():平方根。
    rand():随机数。

    四、条件

    awk允许指定输出条件,只输出符合条件的行。

    awk '条件 动作' 文件名

    下面是输出包含test1的行

    [root@Server-n93yom tmp]# awk -F ':' '/test1/ {print  $(NF-1)}' passwd
    /home/test1
    [root@Server-n93yom tmp]#

    输出行数是偶数的行

    [root@Server-n93yom tmp]# awk -F ':' 'NR%2 == 0 {print NR ")" $(NF-1)}' passwd
    2)/bin
    4)/var/adm
    6)/sbin
    8)/sbin
    10)/root
    12)/var/ftp
    14)/
    16)/
    18)/dev/null
    20)/var/empty/sshd
    22)/home/cfyuser
    24)/etc/rabbitmq
    26)/home/prometheus
    28)/home/logstash
    30)/opt/cloudchef/tomcat
    32)/home/test1

    输出前4行

    [root@Server-n93yom tmp]# awk -F ':' 'NR<=4 {print NR ")" $(NF-1)}' passwd
    1)/root
    2)/bin
    3)/sbin
    4)/var/adm

    输出第一个字段为nginx或tomcat的行

    [root@Server-n93yom tmp]# awk -F ':' '$1=="nginx" || $1=="tomcat" {print $1}' passwd
    nginx
    tomcat
    [root@Server-n93yom tmp]# awk -F ':' '$1=="nginx" || $1=="tomcat" {print NR ")" $1}' passwd
    29)nginx
    30)tomcat

    五、if语句

    输出第一个字段的第一个字符大于t的行

    [root@Server-n93yom tmp]# awk -F ':' ' {if($1>"t") print $1}' passwd
    tss
    tomcat
    test
    test1

    还可以使用else把未匹配到的用----输出

    [root@Server-n93yom tmp]# awk -F ':' ' {if($1>"t") print $1; else print "------" }' passwd
    ------
    ------
    ------
    ------
    ------
    ------
    ------
    ------
    ------
    ------
    ------
    ------
    ------
    ------
    ------
    ------
    ------
    tss
    ------
    ------
    ------
    ------
    ------
    ------
    ------
    ------
    ------
    ------
    ------
    tomcat
    test
    test1

    LeetCode题型

    给定一个文件 file.txt,转置它的内容。

    你可以假设每行列数相同,并且每个字段由 ' ' 分隔.

    示例:

    假设 file.txt 文件内容如下:

    name age
    alice 21
    ryan 30


    应当输出:

    name alice ryan
    age 21 30

    awk是一行一行地处理文本文件,运行流程是:

    先运行BEGIN后的{Action},相当于表头
    再运行{Action}中的文件处理主体命令
    最后运行END后的{Action}中的命令
    有几个经常用到的awk常量:NF是当前行的field字段数;NR是正在处理的当前行数。

    注意到是转置,假如原始文本有m行n列(字段),那么转置后的文本应该有n行m列,即原始文本的每个字段都对应新文本的一行。我们可以用数组res来储存新文本,将新文本的每一行存为数组res的一个元素。

    在END之前我们遍历file.txt的每一行,并做一个判断:在第一行时,每碰到一个字段就将其按顺序放在res数组中;从第二行开始起,每碰到一个字段就将其追加到对应元素的末尾(中间添加一个空格)。

    文本处理完了,最后需要输出。在END后遍历数组,输出每一行。注意printf不会自动换行,而print会自动换行。

    awk '{
        for (i=1;i<=NF;i++){
            if (NR==1){
                res[i]=$i
            }
            else{
                res[i]=res[i]" "$i
            }
        }
    }END{
        for(j=1;j<=NF;j++){
            print res[j]
        }
    }' file.txt

    参考:http://www.ruanyifeng.com/blog/2018/11/awk.html

             http://www.zsythink.net/archives/tag/awk/

            https://www.runoob.com/linux/linux-comm-awk.html

           https://leetcode-cn.com/problems/transpose-file/solution/awkming-ling-yong-shu-zu-chu-cun-dai-shu-chu-jie-g/

  • 相关阅读:
    停滞的代码
    民兵葛二蛋大结局
    该开始BS了
    今天写出了第一个.NetBS应用
    读源码,仿照
    MVN,老天怎么回事?
    从哪里入手
    学习Java了
    工厂方法模式与简单工厂
    转:悟透JavaScript
  • 原文地址:https://www.cnblogs.com/guanbin-529/p/11380604.html
Copyright © 2020-2023  润新知