• linux命令—awk(二)


    awk可以处理大文件

    因为awk处理文件是一行一行的处理,所以当内存空间不足时awk可以处理大文件,而cat命令不能处理一个超过内存大小的文件,因为cat是一次性全部读取文件里面的内容。

    下面用实验证明这个结论:

    free

    free 查看内存使用的命令
    -m 以M为单位显示内存的使用情况
    -h 以人类能够读的懂的格式显示
    B = bytes K = kilos M = megas G = gigas
    T = teras
    P = petas

    [root@localhost 75]# free -m
                  total        used        free      shared  buff/cache   available
    Mem:            972         176         110          12         684         621
    Swap:          2047           1        2046
    [root@localhost 75]#
    
    • 1
    • 2
    • 3
    • 4
    • 5

    Mem: memory 内存
    total 是总的物理内存(内存条的大小)
    used 使用了多少内存
    free 剩余多少内存
    shared 共享内存消耗的空间 --》进程和进程之间通信
    buff/cache --》buffer cache 缓存
    buffer : data from memory to disk
    cache : data from disk to memory

    available: 可用的内存空间

    一个新的进程它可以使用的内存的空间=free + buff和cache里的可用

    缓存的使用空间,可以释放的

    告诉内核去释放缓存的空间:

    [root@localhost 75]# echo 3 >/proc/sys/vm/drop_caches
    [root@localhost 75]# free -h
                  total        used        free      shared  buff/cache   available
    Mem:           972M        144M        773M         10M         54M        725M
    Swap:          2.0G        3.5M        2.0G
    
    • 1
    • 2
    • 3
    • 4
    • 5

    /proc 是内核文件系统,内核是一个软件,控制操作系统的硬件,管理cpu,内存,磁盘,网卡等硬件
    process
    /proc文件系统 消耗也是内存的空间
    sys 系统system
    vm virtual memory 虚拟内存=物理内存+交换分区
    物理内存:8G
    10G
    交换分区:swap 20G 从磁盘里划分出来的一块空间,用来当作内存使用 速度比较慢
    将不活跃的进程临时存放到交换分区(冷宫)
    page in
    page out

    什么时候算内存不足

    查看系统给定的内存空间

    # 当内存空间剩余30%时,内存空间不足
    [root@lier 705]# cat /proc/sys/vm/swappiness 
    30
    
    • 1
    • 2
    • 3

    内核参数优化,提升进程使用的效率,告诉系统尽可能多使用物理内存,物理内存速度快。

    系统开机启动的时候,内核会读取这个配置文件,进行相关参数的设置/etc/sysctl.conf

    root@aliyun-sz:~# cat /etc/sysctl.conf
    vm.swappiness = 0
    kernel.sysrq = 1
    net.ipv4.neigh.default.gc_stale_time = 120
    
    # see details in https://help.aliyun.com/knowledge_detail/39428.html
    net.ipv4.conf.all.rp_filter = 0
    net.ipv4.conf.default.rp_filter = 0
    net.ipv4.conf.default.arp_announce = 2
    net.ipv4.conf.lo.arp_announce = 2
    net.ipv4.conf.all.arp_announce = 2
    
    # see details in https://help.aliyun.com/knowledge_detail/41334.html
    net.ipv4.tcp_max_tw_buckets = 5000
    net.ipv4.tcp_syncookies = 1
    net.ipv4.tcp_max_syn_backlog = 1024
    net.ipv4.tcp_synack_retries = 2
    net.ipv4.tcp_slow_start_after_idle = 0
    
    root@aliyun-sz:~#
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    使用top命令动态监控系统状态

    [root@lier 705]# top
    top - 05:03:34 up 1 day,  9:06,  4 users,  load average: 0.01, 0.03, 0.05
    Tasks: 113 total,   1 running, 112 sleeping,   0 stopped,   0 zombie
    %Cpu(s):  0.0 us,  0.3 sy,  0.0 ni, 99.5 id,  0.0 wa,  0.0 hi,  0.2 si,  0.0 st
    
    • 1
    • 2
    • 3
    • 4
    [root@localhost 75]# time cat sc_bigfile.txt |wc -l
    43017128
    
    real	0m3.595s
    user	0m0.495s
    sys	0m2.927s
    [root@localhost 75]# time tail -1 sc_bigfile.txt
    username    feng43017128  uid:19509
    
    real	0m0.002s
    user	0m0.001s
    sys	0m0.001s
    [root@localhost 75]#
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    # 连续的空格和:当作一个分割符号
    [root@localhost 75]# awk -F"[ :]+" '{print $2,$4}' sc_bigfile.txt
    
    • 1
    • 2
    # tr -s " " 将连续的空格压缩成一个空格
    [root@localhost 75]# head sc_bigfile.txt |tr -s " "|awk -F"[ :]"  '{print $1,$4}'
    
    • 1
    • 2

    substr

    substr是awk语言中的一个内置函数

    substr(s, i [, n]) Return the at most n-character substring of s starting at i. If n is omitted, use the rest of s.

    s是指定的字段,i是从s字段的第i个开始数,n表示n个

    [root@localhost 75]# cat test.txt
    	2022-7-1 00:01:01 78
    	2022-7-1 00:01:04 89
    	2022-7-1 00:03:01 178
    	2022-7-1 00:03:05 890
    	2022-7-2 00:03:01 178
    	2022-7-3 00:03:05 890
    	2022-7-30 00:03:01 178
    	2022-7-31 00:07:05 8900
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    # 截取第一个字段的从第1个字符开始数4个
    [root@localhost 75]# cat test.txt |awk '{print substr($1,1,4)}'
    2022
    2022
    2022
    2022
    2022
    2022
    2022
    2022
    # 截取第一个字段的从第6个字符开始数1个
    [root@localhost 75]# cat test.txt |awk '{print substr($1,6,1)}'
    7
    7
    7
    7
    7
    7
    7
    7
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    练习

    算出2022年7月份里的每一个分钟的流量,具体日志文件格式如下:
    2022-7-1 00:01:01 78
    2022-7-1 00:01:04 89
    2022-7-1 00:03:01 178
    2022-7-1 00:03:05 890
    2022-7-2 00:03:01 178
    2022-7-3 00:03:05 890

    2022-7-30 00:03:01 178
    2022-7-31 00:07:05 8900

    [root@localhost 75]# awk '{time[$1,substr($1,5,1),substr($2,1,5)]+=$3}END{for (i in time)print i,time[i]}'  test.txt |sort -n -k 3 -t -
    2022-7-1-00:01 167
    2022-7-1-00:03 1068
    2022-7-2-00:03 178
    2022-7-3-00:03 890
    2022-7-30-00:03 178
    2022-7-31-00:07 8900
    [root@localhost 75]#
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    time[$1,substr($1,5,1),substr($2,1,5)]+=$3 表示将年月日和小时分钟(substr($2,1,5))拼接作为key,流量($3)作为value,将每分钟的流量相加再用for循环输出统计后的每分钟的流量

    使用awk进行求和运算

    统计用户uid大于1000并且shell是使用bash的用户的数量

    [root@localhost 75]# awk  -F: 'BEGIN{num=0}$3>1000 && $NF ~ /bash/{print $0;num++}END{print num}'  /etc/passwd
    bashzhang:x:1004:1004::/home/bashzhang:/bin/bash
    liu1:x:1006:1006::/home/liu1:/bin/bash
    zhangliu1:x:1007:1007::/home/zhangliu1:/bin/bash
    liu:x:1008:1008::/home/liu:/bin/bash
    fengdeyong:x:1011:1011::/home/fengdeyong:/bin/bash
    5
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    awk中的字段求和(累加)

    [root@localhost lianxi]# cat grade.txt
    id   name    chinese    english    math
    1    cali    80		80	   80
    2    tom     90         90         70
    3    jarry   70         100        90
    
    12    cali    80		80	   80
    11    tom     90         90         70
    13    jarry   70         100        90
    [root@localhost lianxi]# awk 'NR>1{sum+=$3}END{print sum}'  grade.txt
    480
    [root@localhost lianxi]# awk 'BEGIN{sum=0}NR>1{sum+=$3}END{print sum}'grade.txt
    480
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    awk的内置函数length,substr

    统计没有设置密码的用户的数量,同时输出用户名
    /etc/shadow

    [root@localhost lianxi]# awk -F: 'length($2)<=2 {print $1;sum++}END{print sum}'  /etc/shadow
    
    • 1

    统计没有设置密码的用户的数量,同时输出用户名前2个字符

    [root@localhost lianxi]# awk -F: 'length($2)<=2 {print substr($1,1,2);sum++}END{print sum}'  /etc/shadow
    
    • 1

    练习

    1.只显示df -h结果的第一列文件系统

    [root@lier 705]# df -h|awk '{print $1}'
    文件系统
    devtmpfs
    tmpfs
    tmpfs
    tmpfs
    /dev/mapper/centos-root
    /dev/sda1
    tmpfs
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    2.显示passwd文件的第5行和第10行的行号和用户名

    [root@lier 705]# awk -F: 'NR==5 || NR==10 {print NR,$1}' /etc/passwd
    5 lp
    10 operator
    
    • 1
    • 2
    • 3

    3.使用NF变量显示passwd文件倒数第二列的内容

    [root@lier 705]# awk -F: '{print $(NF-1)}' /etc/passwdxxxxxxxxxx awk -F: '{print $(NF-1)}' /etc/passwd[root@lier 705]# awk -F: '{print $(NF-1)}' /etc/passwd
    
    • 1

    4.显示passwd文件中第5到第10行的用户名

    [root@lier 705]# awk -F: 'NR>=5 && NR<=10{print $1}' /etc/passwd
    lp
    sync
    shutdown
    halt
    mail
    operator
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    5.显示passwd文件中第7列不是bash的用户名

    [root@lier 705]# awk -F: '$3<1000{print $1}' /etc/passwd
    
    • 1

    6.显示passwd文件中行号是5结尾的行号和整行内容

    [root@lier 705]# awk -F: 'NR ~/5$/{print NR,$0}' /etc/passwd
    5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
    15 systemd-bus-proxy:x:999:997:systemd Bus Proxy:/:/sbin/nologin
    25 chx:x:1004:1004::/home/chx:/bin/bash
    35 luoyawei:x:1041:1041::/home/luoyawei:/bin/bash
    45 zhaojunjie:x:7797:7797::/home/zhaojunjie:/bin/bash
    55 user8:x:7807:7808::/home/user8:/bin/bash
    65 user18:x:7817:7818::/home/user18:/bin/bash
    75 user08:x:7827:7828::/home/user08:/bin/bash
    85 lyl:x:10004:10004::/home/lyl:/bin/bash
    95 cali10:x:10014:10014::/home/cali10:/bin/bash
    105 cali20:x:10024:10024::/home/cali20:/bin/bash
    115 mi:x:10034:10034::/home/mi:/bin/bash
    125 yueyang:x:10045:10042::/home/yueyang:/bin/bash
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    7.用ifconfig/ip add 只显示ip
    yum install net-tools -y -->安装ifconfig命令的软件

    [root@lier 705]# ifconfig|awk 'NR==2{print $NF}'
    192.168.1.255
    
    • 1
    • 2

    8.ifconfig 命令后使用awk显示ens33的入站流量和出站流量(字节)

    [root@lier 705]# ifconfig|awk 'NR==5 || NR==7{print $1,$5}'
    RX 336596366
    TX 1445420475
    
    • 1
    • 2
    • 3

    9.使用awk命令统计以r开头的用户数目,显示如下效果

    [root@lier 705]# awk 'BEGIN{num=0}/^r/{num+=1}END{print num}' /etc/passwd
    1
    
    • 1
    • 2

    10.显示每隔2秒的流量的变化
    [root@lamp-test ~]# watch -n 2 -d “ifconfig|awk ‘NR==5{print $5}’”
    11.统计/etc/passwd文件里以r开头的用户的数量,并且显示出用户名

    [root@lier 705]# awk -F: 'BEGIN{num=0}/^r/{print $1;num+=1}END{print num}' /etc/passwd
    root
    1
    
    • 1
    • 2
    • 3

    awk使用shell变量

    img

    [root@lier 705]# echo |awk -F: -v username=$name '{print username}'
    mengmeng
    [root@lier 705]# ls |awk -F: -v username=$name '{print username}'
    mengmeng
    mengmeng
    
    • 1
    • 2
    • 3
    • 4
    • 5

    img

    [root@lier 705]# awk -F: "\$1~/$mn/{print \$0}" /etc/passwd
    mengmeng:x:10049:10049::/home/mengmeng:/bin/bash
    mengmeng1:x:10050:10050::/home/mengmeng1:/bin/bash
    mengmeng12:x:10051:10051::/home/mengmeng12:/bin/bash
    
    • 1
    • 2
    • 3
    • 4

    if语句

    img

    单分支

    [root@lier 705]# cat /etc/passwd|awk -F: 'length($1)==3{print $0}'
    bin:x:1:1:bin:/bin:/sbin/nologin
    adm:x:3:4:adm:/var/adm:/sbin/nologin
    ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
    tss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin
    lwq:x:1002:1002::/home/lwq:/bin/bash
    chx:x:1004:1004::/home/chx:/bin/bash
    lqt:x:1010:1010::/home/lqt:/bin/bash
    lyl:x:10004:10004::/home/lyl:/bin/bash
    
    [root@lier 705]# cat /etc/passwd|awk -F: '{if (length($1)==3) print $0}'
    bin:x:1:1:bin:/bin:/sbin/nologin
    adm:x:3:4:adm:/var/adm:/sbin/nologin
    ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
    tss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin
    lwq:x:1002:1002::/home/lwq:/bin/bash
    chx:x:1004:1004::/home/chx:/bin/bash
    lqt:x:1010:1010::/home/lqt:/bin/bash
    lyl:x:10004:10004::/home/lyl:/bin/bash
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    双分支

    [root@lier 705]# cat /etc/passwd|awk -F: '{if (length($1)==3) print $0;else print $1}'
    
    • 1

    多分支

    找出超级用户、系统用户、普通用户

    awk -F: '{if ($3==0) print $1,"为超级用户";else if($3>0 && $3<1000) print $1,"为系统用户";else print $1,"为普通用户"}' /etc/passwd
    
    • 1

    找出超级用户、系统用户、普通用户并统计用户数量

    [root@lier 705]# awk -F: '{if ($3==0) {print $1,"为超级用 户";num1++;}else if($3>0 && $3<1000) {print $1,"为系统用户";num2++;}else {print $1,"为普通用户";num3++}}END{print " 超级用户的数量是:"num1,"系统用户的数量:"num2,"普通用户的数量:"num3}' /etc/passwd
    
    • 1

    for循环

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DkZcYT5S-1657026505736)(C:\Users\lier\AppData\Roaming\Typora\typora-user-images\image-20220705165522617.png)]

    [root@lier 705]# awk -F: '{user[$1]=$3}END{for (i in user) print user[i]}' /etc/passwd
    
    • 1

    练习

    练习: 对nginx的日志文件access.log进行分析,分析出单个ip地址累计下载获取的文件大小的总数(对每次访问数据的大小进行求和),显示下载总数最大的前100个ip地址和下载文件大小,按照下载文件大小的降序排列

    [root@lier 705]# awk '{access[$1]+=$10}END{for (i in access) print i,access[i]}' access.log |sort -k 2 -n -r|head -100 result.txt
    
    • 1

    以下是nginx日志的字段含义

    t i m e i s o 8601 ∣ time_iso8601| timeiso8601host| h t t p c f c o n n e c t i n g i p ∣ http_cf_connecting_ip| httpcfconnectingiprequest| s t a t u s ∣ status| statusbody_bytes_sent| h t t p r e f e r e r ∣ http_referer| httprefererhttp_user_agent

    -------------------------------------

    2019-04-25T09:51:58+08:00|a.google.com|47.52.197.27|GET /v2/depth?symbol=aaa HTTP/1.1|200|24|-|apple

    2019-04-25T09:52:58+08:00|b.google.com|47.75.159.123|GET /v2/depth?symbol=bbb HTTP/1.1|200|407|-|python-requests/2.20.0

    2019-04-25T09:53:58+08:00|c.google.com|13.125.219.4|GET /v2/ticker?timestamp=1556157118&symbol=ccc HTTP/1.1|200|162|-|chrome

    2019-04-25T09:54:58+08:00|d.shuzibi.co|-||HEAD /justfor.txt HTTP/1.0|200|0|-|-

    2019-04-25T09:55:58+08:00|e.google.com|13.251.98.2|GET /v2/order_detail?apiKey=ddd HTTP/1.1|200|231|-|python-requests/2.18.4

    2019-04-25T09:56:58+08:00|f.google.com|210.3.168.106|GET /v2/trade_detail?apiKey=eee HTTP/1.1|200|24|-|-

    2019-04-25T09:57:58+08:00|g.google.com|47.75.115.217|GET /v2/depth?symbol=fff HTTP/1.1|200|397|-|python-requests/2.18.4

    2019-04-25T09:58:58+08:00|h.google.com|47.75.58.56|GET /v2/depth?symbol=ggg HTTP/1.1|200|404|-|safari

    2019-04-25T09:59:58+08:00|i.google.com|188.40.137.175|GET /v2/trade_detail?symbol=hhh HTTP/1.1|200|6644|-|-

    2019-04-25T10:01:58+08:00|j.google.com|2600:3c01:0:0:f03c:91ff:fe60:49b8|GET /v2/myposition?apiKey=jjj HTTP/1.1|200|110|-|scan

    1、计算每分钟的带宽(body_bytes_sent)

    [root@lier 705]# awk -F"|" '{flow[substr($1,1,16)]+=$(NF-2)}END{for (i in flow) print i,flow[i]}' nginx.log 
    2019-04-25T10:01 110
    2019-04-25T09:56 24
    2019-04-25T09:57 397
    2019-04-25T09:58 404
    2019-04-25T09:59 6644
    2019-04-25T09:51 24
    2019-04-25T09:52 407
    2019-04-25T09:53 162
    2019-04-25T09:54 0
    2019-04-25T09:55 231
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    2、统计每个URI(即不带问号?前面的内容)的每分钟的频率
    /v2/myposition?apiKey=jjj 中的/v2/myposition

    [root@lier 705]# awk -F"[| ?]+" '{flow[substr($1,1,16)$5]+=1}END{for (i in flow) print i,flow[i]}' nginx.log 
    2019-04-25T09:55/v2/order_detail 1
    2019-04-25T10:01/v2/myposition 1
    2019-04-25T09:59/v2/trade_detail 1
    2019-04-25T09:53/v2/ticker 1
    2019-04-25T09:58/v2/depth 1
    2019-04-25T09:57/v2/depth 1
    2019-04-25T09:52/v2/depth 1
    2019-04-25T09:51/v2/depth 1
    2019-04-25T09:56/v2/trade_detail 1
    2019-04-25T09:54/justfor.txt 1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
  • 相关阅读:
    《JAVA设计模式系列》责任链模式
    【MySQL】数据类型
    【Java面试】Cookie和Session的区别
    快速排序(非递归)和归并排序
    python实战故障诊断之CWRU数据集(三):信号预白化处理-倒谱预白化(CEP pre-whitening)
    R语言使用dt函数生成t分布密度函数数据、使用plot函数可视化t分布密度函数数据(t Distribution)
    ubuntu未开启ssh
    ChatGPT的基础知识
    Vue3问题:如何实现密码加密登录?前后端!
    三、react组件的生命周期
  • 原文地址:https://blog.csdn.net/liwenqianye/article/details/125628107