这篇文章用来记录一下在牛客网刷的题,记录一下思想,顺便学习一下shell脚本。这篇主要记录SHELL篇的刷题过程。

11. 转置文件的内容

题目描述

写一个bash脚本来转置文本文件nowcoder.txt中的文件内容。
文件中每行列数相同,并且每个字段由空格分隔
示例:
假设 nowcoder.txt 内容如下:
job salary
c++ 13
java 14
php 12

你的脚本应当输出(以词频升序排列):
job c++ java php
salary 13 14 12

解题思路

这一题的核心要求是将每一列的内容变成行,也就是将第一列变成第一行,第二列变成第二行……。

12. 打印每一行出现的数字个数

问题描述

写一个bash脚本,统计一个文本文件nowcoder.txt中每一行出现的1~5数字的个数,并且计算一下整个文档中一共出现了几个1~5数字的总数。

示例:
假设 nowcoder.txt 内容如下:
a12b8
10ccc
2521abc
9asf
你的脚本应当输出:
line1 number: 2
line2 number: 1
line3 number: 4
line4 number: 0
sum is 7

解题思路

这一题的要求是统计每一行出现的1~5数字的个数,有两个解题思路:

  1. grep 命令,grep 命令有一个-o参数输出所有匹配的,然后配合wc -l统计总出现个数。这里要求输出每一行的,所以就遍历每一行然后用grep -o '[1-5]' | wc -l 统计每一行的数字出现个数,用一个全局变量统计总的就行了.

#!/bin/bash
i=1
sum=0
while IFS= read -r line; do
    cnt=$(grep -o '[1-5]' $line)
    echo "line$i number: $cnt"
    ((i++))
    ((sum+=$cnt))
done < nowcoder.txt
echo "sum is $sum"
  1. 直接awk 命令一行统计。这个方法的核心是用需要统计的这些数字作为分隔符,分割每一行,分割后的列数减1就是统计数字的个数。原理很简单,一块蛋糕切一刀变成两块,这里这一刀就是变成分隔符的数字,一刀对应两块蛋糕,两刀对应三块蛋糕,因此符合条件的数字个数就是分割之后列数减1。

awk -F [12345] '{print "line" NR, "number:", NF - 1; sum += NF - 1} END{print "sum is", sum}' nowcoder.txt

14. 求平均值

问题描述

写一个bash脚本以实现一个需求,求输入的一个数组的平均值

第1行为输入的数组长度N
第2~N行为数组的元素,如以下为:
数组长度为4,数组元素为1 2 9 8
示例:
4
1
2
9
8

那么平均值为:5.000(保留小数点后面3位)
你的脚本获取以上输入应当输出:
5.000

解题思路

这题就是正常的累加求平均。

#!/bin/bash

sum=0
read n
for ((i=1; i <= n; i++))
do
    read m
    sum=$(($sum+$m))
done
echo "scale=3;$sum/$n" | bc
exit 0

16. 判断输入的是否为IP地址

问题描述

写一个脚本统计文件nowcoder.txt中的每一行是否是正确的IP地址。
如果是正确的IP地址输出:yes
如果是错误的IP地址,且是四段号码的话输出:no,否则的话输出:error
假设nowcoder.txt内容如下:
192.168.1.1
192.168.1.0
300.0.0.0
123
你的脚本应该输出:
yes
yes
no
error

解题思路

这题的要求是判断nowcoder.txt里面每一行的内容地址是否是ip地址格式,如果是再判断这个ip地址是否合法。如果正确合法输出yes,如果不是ip地址输出error,如果是ip地址格式但不合法就输出no

首先搞懂ip地址的定义,ip地址由四段组成通过.分割,每一段由8个比特位构成所以每一段的范围是0~255 。通常全0或全1由特殊作用,这里应该不用考虑,判断每一段的范围是0~255就够了。这一题主要用awk解决,用awk简单快。

. 作为分隔符,正确的ip地址会被划分成四段,NF4 ,所以NF不为4的情况为非法ip地址直接输出error。下一层再判断每一段的值范围是否在0~255之间 。完整的代码如下:

#!/bin/bash

awk -F"." '{
    if (NF != 4) {
        print "error"
    } else {
        if ($1 > 255 || $1 < 0 || $2 > 255 || $2 < 0 || $3 > 255 || $3 < 0 || $4 > 255 || $4 < 0) {
            print "no"
        } else {
            print "yes"
        }
    }
}' nowcoder.txt

exit 0

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

问题描述

假设命令运行的结果我们存储在nowcoder.txt里,格式如下:
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.1  37344  4604 ?        Ss    2020   2:13 /sbin/init
root       231  0.0  1.5 166576 62740 ?        Ss    2020  15:15 /lib/systemd/systemd-journald
root       237  0.0  0.0      0     0 ?        S<    2020   2:06 [kworker/0:1H]
root       259  0.0  0.0  45004  3416 ?        Ss    2020   0:25 /lib/systemd/systemd-udevd
root       476  0.0  0.0      0     0 ?        S<    2020   0:00 [edac-poller]
root       588  0.0  0.0 276244  2072 ?        Ssl   2020   9:49 /usr/lib/accountsservice/accounts-daemon
message+   592  0.0  0.0  42904  3032 ?        Ss    2020   0:01 /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation
root       636  0.0  0.0  65532  3200 ?        Ss    2020   1:51 /usr/sbin/sshd -D
daemon     637  0.0  0.0  26044  2076 ?        Ss    2020   0:00 /usr/sbin/atd -f
root       639  0.0  0.0  29476  2696 ?        Ss    2020   3:29 /usr/sbin/cron -f
root       643  0.0  0.0  20748  1992 ?        Ss    2020   0:26 /lib/systemd/systemd-logind
syslog     645  0.0  0.0 260636  3024 ?        Ssl   2020   3:17 /usr/sbin/rsyslogd -n
root       686  0.0  0.0 773124  2836 ?        Ssl   2020  26:45 /usr/sbin/nscd
root       690  0.0  0.0  19472   252 ?        Ss    2020  14:39 /usr/sbin/irqbalance --pid=/var/run/irqbalance.pid
ntp        692  0.0  0.0  98204   776 ?        Ss    2020  25:18 /usr/sbin/ntpd -p /var/run/ntpd.pid -g -u 108:114
uuidd      767  0.0  0.0  28624   192 ?        Ss    2020   0:00 /usr/sbin/uuidd --socket-activation
root       793  0.0  0.0 128812  3148 ?        Ss    2020   0:00 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
www-data   794  0.0  0.2 133376  9120 ?        S     2020 630:57 nginx: worker process
www-data   795  0.0  0.2 133208  8968 ?        S     2020 633:02 nginx: worker process
www-data   796  0.0  0.2 133216  9120 ?        S     2020 634:24 nginx: worker process
www-data   797  0.0  0.2 133228  9148 ?        S     2020 632:56 nginx: worker process
web        955  0.0  0.0  36856  2112 ?        Ss    2020   0:00 /lib/systemd/systemd --user
web        956  0.0  0.0  67456  1684 ?        S     2020   0:00 (sd-pam)
root      1354  0.0  0.0   8172   440 tty1     Ss+   2020   0:00 /sbin/agetty --noclear tty1 linux
root      1355  0.0  0.0   7988   344 ttyS0    Ss+   2020   0:00 /sbin/agetty --keep-baud 115200 38400 9600 ttyS0 vt220
root      2513  0.0  0.0      0     0 ?        S    13:07   0:00 [kworker/u4:1]
root      2587  0.0  0.0      0     0 ?        S    13:13   0:00 [kworker/u4:2]
root      2642  0.0  0.0      0     0 ?        S    13:17   0:00 [kworker/1:0]
root      2679  0.0  0.0      0     0 ?        S    13:19   0:00 [kworker/u4:0]
root      2735  0.0  0.1 102256  7252 ?        Ss   13:24   0:00 sshd: web [priv]
web       2752  0.0  0.0 102256  3452 ?        R    13:24   0:00 sshd: web@pts/0
web       2753  0.5  0.1  14716  4708 pts/0    Ss   13:24   0:00 -bash
web       2767  0.0  0.0  29596  1456 pts/0    R+   13:24   0:00 ps aux
root     10634  0.0  0.0      0     0 ?        S    Nov16   0:00 [kworker/0:0]
root     16585  0.0  0.0      0     0 ?        S<    2020   0:00 [bioset]
root     19526  0.0  0.0      0     0 ?        S    Nov16   0:00 [kworker/1:1]
root     28460  0.0  0.0      0     0 ?        S    Nov15   0:03 [kworker/0:2]
root     30685  0.0  0.0  36644  2760 ?        Ss    2020   0:00 /lib/systemd/systemd --user
root     30692  0.0  0.0  67224  1664 ?        S     2020   0:00 (sd-pam)
root     32689  0.0  0.0  47740  2100 ?        Ss    2020   0:00 /usr/local/ilogtail/ilogtail
root     32691  0.2  0.5 256144 23708 ?        Sl    2020 1151:31 /usr/local/ilogtail/ilogtail
现在需要你统计VSZ,RSS各自的总和(以M兆为统计),输出格式如下
MEM TOTAL
VSZ_SUM:3250.8M,RSS_SUM:179.777M

解题思路

#!/bin/bash

awk '
NR>1{
    vsz_sum+=$5
    rss_sum+=$6
} END {
    print "MEM TOTAL"
    printf "VSZ_SUM:%.1fM,RSS_SUM:%.3fM",vsz_sum/1024, rss_sum/1024
}
' nowcoder.txt
exit 0