• 【牛客编程题】shell34题(Linux awk,grep命令)


    【牛客编程题】shell34题(Linux awk,grep命令)

    SHELL01-22:基本文本处理
    SHELL23-28:nginx日志分析
    SHELL29-32:netstat练习

    做题链接:https://www.nowcoder.com/exam/oj?page=1&tab=SHELL%E7%AF%87&topicId=195

    参考资料:https://github.com/jaywcjlove/linux-command

    从awk命令开始

    awk 是一种编程语言,用于在linux/unix下对文本和数据进行处理。

    它在命令行中使用,但更多是作为脚本来使用。awk有很多类似于C语言的灵活内建的功能,比如数组、函数等。

    awk [options] 'script' var=value file(s)
    awk [options] -f scriptfile var=value file(s)
    
    -F fs,fs指定输入分隔符,fs可以是字符串或正则表达式,如-F : 。默认的分隔符是连续的空格或制表符。
    -v var=value 赋值一个用户定义变量,将外部变量传递给awk
    -f scripfile 从脚本文件中读取awk命令
    
    参考资料:https://wangchujiang.com/linux-command/c/awk.html
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    awk脚本是由模式和操作组成的。

    模式可以是以下任意一个:

    • /正则表达式/, 关系表达式, 模式匹配表达式(~匹配, !~不匹配),
    • BEGIN语句块、pattern语句块、END语句块

    awk脚本基本结构

    awk 'BEGIN{ print "start" } pattern{ commands } END{ print "end" }' file
    
    第一步:执行BEGIN{ commands }语句块中的语句;
    第二步:从文件或标准输入读取一行,然后执行pattern{ commands }语句块,它逐行扫描文件,从第一行到最后一行重复这个过程,直到文件全部被读取完毕。
    第三步:当读至输入流末尾时,执行END{ commands }语句块。
    BEGIN和END是可选的,但是如果没有pattern语句块,则默认执行{ print },即打印每一个读取到的行,awk读取的每一行都会执行该语句块。
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    awk内置变量

    NR: 表示记录数,在执行过程中对应于 当前的行号。
    NF: 表示字段数,在执行过程中对应于 当前的字段数。
    FS:字段分隔符(默认是任何空格)。
    
    使用print $NF可以打印出一行中的最后一个字段,使用$(NF-1)则是打印倒数第二个字段。
    打印每一行的第二和第三个字段:awk '{ print $2,$3 }' filename
    统计文件中的行数:awk 'END{ print NR }' filename
    在读入每一行的时,awk会将NR更新为对应的行号,当到达最后一行NR的值就是最后一行的行号,所以END语句块中的NR就是文件的行数。
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    将外部变量值传递给awk

    借助 -v选项 ,可以将外部值传递给awk
    
    VAR=10000
    echo | awk -v VARIABLE=$VAR '{ print VARIABLE }'
    
    var1="aaa"
    var2="bbb"
    echo | awk '{ print v1,v2 }' v1=$var1 v2=$var2
    
    查找进程pid
    netstat -antup | grep 7770 | awk '{ print $NF NR}' | awk '{ print $1}'
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    对grep命令的补充

    强大的文本搜索工具

    • grep 更适合单纯的查找或匹配文本
    • sed 更适合编辑匹配到的文本
    • awk 更适合格式化文本,对文本进行较复杂格式处理

    grep全面搜索正则表达式并把匹配的行打印出来。用于过滤/搜索的特定字符。

    # grep查找
    grep "match_pattern" file_1 file_2 file_3 ...
    
    # 查找后,输出除之外的所有行 -v
    grep -v "match_pattern" file_name
    
    # 使用正则表达式 -E 
    # 使用正则表达式 -P 选项:
    grep -E "[1-9]+"
    grep -P "(\d{3}\-){2}\d{4}" file_name
    
    # 统计文件或者文本中包含匹配字符串的行数 -c 选项:
    grep -c "text" file_name
    
    # 输出包含匹配字符串的行数 -n 选项
    grep "text" -n file_name
    cat file_name | grep "text" -n
    
    # 在多级目录中对文本进行递归搜索, .表示当前目录。
    grep "text" . -r -n
    
    # 忽略匹配样式中的字符大小写:
    echo "hello world" | grep -i "HELLO"
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    SHELL1 统计文件的行数

    # 查看文件的'\n'的数量
    wc  -l  ./nowcoder.txt
    
    # 执行结果
    8 ./nowcoder.txt
    
    # 用awk打印第一个数字
    wc -l ./nowcoder.txt | awk '{print $1}'
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    SHELL2 打印文件的最后5行

    # 查看文件的前5行,可以使用head命令,如
    head -5 filename
    
    # 查看文件的后5行,可以使用tail命令,如:
    tail -5 filename 或 tail -n 5 filename
    
    # 查看文件中间一段,你可以使用sed命令,如:
    sed -n ‘5,20p’ filename
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    SHELL3 输出7的倍数

    #!/bin/bash
    for num in {0..500..7}; do  
      echo "${num}" 
    done
    
    
    • 1
    • 2
    • 3
    • 4
    • 5

    SHELL4 输出第5行的内容

    # head 命令拿到前五行,再通过通道,通过tail取出来最后一行,即第五行
    head -n 5 nowcoder.txt | tail -n 1 
    
    # sed 命令中的 p 子命令,打印第五行
    sed -n 5p nowcoder.txt
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    SHELL5 打印空行的行号

    # awk是数据解析工具 对文件或管道数据、终端输入数据逐行解析 默认以空格分隔
    # awk语法:awk 'pattern{命令}' 文件名, /pattern/是正则表达式匹配, /^$/表示空字符串
    
    awk '/^$/{print NR}' nowcoder.txt
    
    
    • 1
    • 2
    • 3
    • 4
    • 5

    SHELL6 去掉空行

    # awk 命令,判断当前行的内容然后输出
    awk '!/^$/ {print $NF}' nowcoder.txt
    awk '{if($0 != "") {print $0}}' nowcoder.txt
    
    # cat 输出文本内容,然后通过管道符交由 awk 做非空校验然后输出
    cat nowcoder.txt | awk NF
    
    # grep 命令 -v 显示不包含匹配文本的所有行
    grep -v '^$'
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    SHELL7 打印字母数小于8的单词

    # awk嵌套for
    awk -F " " '{for(i=1;i<=NF;i++){if(length($i) < 8){print $i}}}' nowcoder.txt
    
    # 或者循环
    for i in $(cat nowcoder.txt); do
        if [ ${#i} -lt 8 ]; then
            echo ${i}
        fi
    done
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    SHELL8 统计所有进程占用内存大小的和

    # 利用awk的强大功能
    awk '{sum+=$6}END{print sum}' nowcoder.txt
    
    
    • 1
    • 2
    • 3

    SHELL9 统计每个单词出现的个数

    # awk天下无敌
    awk '{for(i=1;i<=NF;i++) a[$i]+=1}END{for(x in a) print x,a[x]}' nowcoder.txt
    
    
    
    • 1
    • 2
    • 3
    • 4

    SHELL10 第二列是否有重复

    # awk
    awk '{a[$2]+=1}END{for(x in a){if(a[x]>1) print a[x],x}}' nowcoder.txt
    
    
    • 1
    • 2
    • 3

    SHELL11 转置文件的内容

    # awk
    awk '{
        for(i=1;i<=NF;i++){
          if(NR==1){
            row[i] = $i;
          }else{
            row[i] = row[i]" "$i;
          }
        }
    }END{
      for(i=1;i<=NF;i++){
        print row[i]
      }
    }' nowcoder.txt
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    SHELL12 打印每一行出现的数字个数

    # awk
    awk -F "[1,2,3,4,5]" '
    BEGIN{sum=0}
    {print "line"NR" number:"(NF-1);sum+=(NF-1)}
    END{print "sum is "sum}
    ' nowcoder.txt
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    SHELL13 去掉所有包含this的句子

    # grep 命令 -v 显示不包含匹配文本的所有行
    grep -v 'this'
    
    # awk 命令,检查当前 $0 不包含 this 随机输出
    awk '$0!~/this/ {print $0}'
    
    • 1
    • 2
    • 3
    • 4
    • 5

    SHELL14 求平均值

    awk '{if(NR==1) {N=$1} else{sum+=$1}} END{printf ("%.3f",sum/N) }'
    
    • 1

    SHELL15 去掉不需要的单词

    # 使用grep -v去掉
    grep  -E -v "[bB]"
    
    # awk
    awk '{ for (i=1; i<=NF; i++) { if ($i ~ /.*[bB]+.*/) { continue } else { print $i } } }' 
    
    • 1
    • 2
    • 3
    • 4
    • 5

    SHELL16 判断输入的是否为IP地址

    # 使用 . 作为分隔符
     awk -F '.' '{
         if (NF == 4) {
             for (i = 1; i < 5; i++) {
                 if ($i > 255 || $i < 0) {
                     print("no")
                     break
                 }
             }
             if (i == 5) {
                 print("yes")
             } else {
                 print("error")
             }
         }   
     }'
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    SHELL17 将字段逆序输出文件的每行

    awk -F ":" '{a[NR]=$NF; for (i=NF-1;i>0;i--) a[NR]=a[NR]":"$i }END{for(k in a) print a[k]}' nowcoder.txt
    
    • 1

    SHELL18 域名进行计数排序处理

    awk -F/ '{print $3}'|sort -r|uniq -c|awk '{print $1,$2}'
    
    
    • 1
    • 2

    SHELL19 打印等腰三角形

    awk 'BEGIN{
        for(n = 1; n <= 5; n++){
            row = "";
            for(i = 1;i <= 5 - n; i++){
                row = row " "
            }
            for(i = 1; i <= n; i++){
                row = row "*" " "
            }
            print row
        }
    }'
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    SHELL20 打印只有一个数字的行

    awk -F[1-9] '{if(NF==2)print $0}'
    
    • 1

    SHELL21 格式化输出

    awk 'BEGIN{FS=""}{for(i=1;i<=NF;i++) {if((NF-i)%3==0&&i!=NF) printf $i",";else printf $i};printf "\n"}' nowcoder.txt 
    
    • 1

    SHELL22 处理文本

    awk -F ":" '{
    	a[$1] = a[$1] $2 "\n"
    } 
    END {for (i in a){
    	printf("[%s]\n%s",i,a[i])
    } 
    }' nowcoder.txt
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    SHELL23 nginx日志分析1-IP统计

    # 利用 awk 中的 substr 函数
    awk '{
        if(substr($4, 2, 11) == "23/Apr/2020") {
            res[$1]++;
        }
    }END {
        for(k in res) {
            print res[k] " " k
        }
    }' | sort -nr -k 1 -t " "
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    SHELL24 nginx日志分析2-统计某个时间段的IP

    # 使用grep
    grep "23/Apr/2020" | cut -c '-12' | sort -u | wc -l
    
    # awk
    awk '{
    	if ($0 ~ /\[23\/Apr\/2020:2[0-2]/) {
             a[$1]=1
         } 
    } END {
         print (length(a))
    }'
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    SHELL25 nginx日志分析3-统计访问3次以上的IP

    awk '{
        if ($1 in a) {
            a[$1]++;
        } else {
            a[$1]=1
        }
    } END {
        for (j in a) {
            if (a[j] > 3) {
                print a[j],j
            }
        }
    }' nowcoder.txt | sort -r
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    SHELL26 nginx日志分析4-查询某个IP的详细访问情况

    awk '$1=="192.168.1.22"{a[$7]++}END{ for(i in a){ print a[i],i } }' | sort -r 
    
    
    • 1
    • 2

    SHELL27 nginx日志分析5-统计爬虫抓取404次数

    # grep
    grep 'www.baidu.com' nowcoder.txt | grep ' 404 ' | wc -l
    
    # awk
    awk '{
    	if ($0 ~ '/www.baidu.com/' && $9 = 404 ) a++
    } END {
    	print a
    }' nowcoder.txt
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    SHELL28 nginx日志分析6-统计每分钟的请求数

    awk '{print substr($4,14,5)}' | sort | uniq -c | sort -rn -k 1 | awk '{print $1,$2}' 
    
    
    • 1
    • 2

    SHELL29 netstat练习1-查看各个状态的连接数

    awk '/tcp/{a[$6]++}END{for(i in a)print i,a[i]}' nowcoder.txt | sort -nrk 2
    
    
    • 1
    • 2

    SHELL30 netstat练习2-查看和3306端口建立的连接

    cat nowcoder.txt | grep '3306' | grep 'ESTABLISHED' | awk -F ' ' '{print $5}' | awk -F: '{print $1}' | sort | uniq -c | sort -nr -k1 | awk '{print $1" "$2}'
    
    
    • 1
    • 2

    SHELL31 netstat练习3-输出每个IP的连接数

    awk -F "[ :]+" '/tcp/{a[$6]++}END{for(i in a)print i,a[i]}' nowcoder.txt | sort -nrk2
    
    
    • 1
    • 2

    SHELL32 netstat练习4-输出和3306端口建立连接总的各个状态的数目

    awk '{
        if ($1 == "tcp" && $5 ~ /3306/) {
            if ($6 == "ESTABLISHED") {
                es++
            }
            ans++
            arr[$5]=0
        }
    } END {
        printf("TOTAL_IP %d\nESTABLISHED %d\nTOTAL_LINK %d", length(arr), es, ans)
    }'
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    SHELL33 业务分析-提取值

    awk -F "[:,]" '{
        if($0~"Server version"){
            print "serverVersion:" $4;
        }
        if($0~"Server number"){
            print "serverName:" $4;
        }
        if($0~"OS Name"){
            print "osName:" $4;
        }
        if($0~"OS Version"){
            print "osVersion:" $6
        }
    }'
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    SHELL34 ps分析-统计VSZ,RSS各自总和

    awk '{
        v += $5
        r += $6
    } END {
        printf("MEM TOTAL\nVSZ_SUM:%0.1fM,RSS_SUM:%0.3fM", v/1024, r/1024)
    }'
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
  • 相关阅读:
    java-net-php-python-7jsp在线购物计算机毕业设计程序
    hbase建表时设置预分区
    MC Layer Target
    SpringMVC:拦截器+文件上传下载, 拦截器
    关于Flask_自定义路由转换器的方法和使用
    五、资源控制器
    示例:WPF中绑定枚举到ComboBox想显示成中文或自定义名称如何实现
    从 Google 离职,前Go 语言负责人跳槽小公司
    后台可视化布局打印设计
    TCP MIN_RTO 辩证考
  • 原文地址:https://blog.csdn.net/qq_33957603/article/details/125935231