【Shell牛客刷题系列】SHELL32 netstat练习4-输出和3306端口建立连接总的各个状态的数目



该系列是基于牛客Shell题库,针对具体题目进行查漏补缺,学习相应的命令。

刷题链接:牛客题霸-Shell篇

该系列文章都放到专栏下,专栏链接为:《专栏:Shell》。欢迎关注专栏~

本文知识预告:

  • 本文复习了awkgrepwcecho命令的相关用法;
  • 然后给出了四种题目的解决方案。


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

假设netstat命令运行的结果我们存储在nowcoder.txt里,格式如下:

Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        0      0 0.0.0.0:6160            0.0.0.0:*               LISTEN
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN
tcp        0      0 172.16.56.200:41856     172.16.34.144:3306      ESTABLISHED
tcp        0      0 172.16.56.200:49822     172.16.0.24:3306        ESTABLISHED
tcp        0      0 172.16.56.200:49674     172.16.0.24:3306        ESTABLISHED
tcp        0      0 172.16.56.200:42316     172.16.34.143:3306      ESTABLISHED
tcp        0      0 172.16.56.200:44076     172.16.240.74:6379      ESTABLISHED
tcp        0      0 172.16.56.200:49656     172.16.0.24:3306        ESTABLISHED
tcp        0      0 172.16.56.200:58248     100.100.142.4:80        TIME_WAIT
tcp        0      0 172.16.56.200:50108     172.16.0.24:3306        ESTABLISHED
tcp        0      0 172.16.56.200:41944     172.16.34.144:3306      ESTABLISHED
tcp        0      0 172.16.56.200:35548     100.100.32.118:80       TIME_WAIT
tcp        0      0 172.16.56.200:39024     100.100.45.106:443      TIME_WAIT
tcp        0      0 172.16.56.200:41788     172.16.34.144:3306      ESTABLISHED
tcp        0      0 172.16.56.200:58260     100.100.142.4:80        TIME_WAIT
tcp        0      0 172.16.56.200:41812     172.16.34.144:3306      ESTABLISHED
tcp        0      0 172.16.56.200:41854     172.16.34.144:3306      ESTABLISHED
tcp        0      0 172.16.56.200:58252     100.100.142.4:80        TIME_WAIT
tcp        0      0 172.16.56.200:49586     172.16.0.24:3306        ESTABLISHED
tcp        0      0 172.16.56.200:41754     172.16.34.144:3306      ESTABLISHED
tcp        0      0 172.16.56.200:50466     120.55.222.235:80       TIME_WAIT
tcp        0      0 172.16.56.200:38514     100.100.142.5:80        TIME_WAIT
tcp        0      0 172.16.56.200:49832     172.16.0.24:3306        ESTABLISHED
tcp        0      0 172.16.56.200:52162     100.100.30.25:80        ESTABLISHED
tcp        0      0 172.16.56.200:50372     172.16.0.24:3306        ESTABLISHED
tcp        0      0 172.16.56.200:50306     172.16.0.24:3306        ESTABLISHED
tcp        0      0 172.16.56.200:49600     172.16.0.24:3306        ESTABLISHED
tcp        0      0 172.16.56.200:41908     172.16.34.144:3306      ESTABLISHED
tcp        0      0 172.16.56.200:60292     100.100.142.1:80        TIME_WAIT
tcp        0      0 172.16.56.200:37650     100.100.54.133:80       TIME_WAIT
tcp        0      0 172.16.56.200:41938     172.16.34.144:3306      ESTABLISHED
tcp        0      0 172.16.56.200:49736     172.16.0.24:3306        ESTABLISHED
tcp        0      0 172.16.56.200:41890     172.16.34.144:3306      ESTABLISHED
udp        0      0 127.0.0.1:323           0.0.0.0:*
udp        0      0 0.0.0.0:45881           0.0.0.0:*
udp        0      0 127.0.0.53:53           0.0.0.0:*
udp        0      0 172.16.56.200:68        0.0.0.0:*
udp6       0      0 ::1:323                 :::*
raw6       0      0 :::58                   :::*                    7

现在需要你输出和本机3306端口建立连接的各个状态的数目,按照以下格式输出

  • TOTAL_IP表示建立连接的ip数目
  • TOTAL_LINK表示建立连接的总数目
TOTAL_IP 3
ESTABLISHED 20
TOTAL_LINK 20

题目要求的有三个要计算的,这才算是名副其实的困难题吧🤣🤣

相关命令学习

awk:文本和数据进行处理的编程语言

awk命令来自于三位创始人”Alfred Aho,Peter Weinberger, Brian Kernighan “的姓氏缩写,其功能是用于对文本和数据进行处理的编程语言。使用awk命令可以让用户自定义函数或正则表达式对文本内容进行高效管理,与sedgrep并称为Linux系统中的文本三剑客。

语法格式awk 参数 文件

常用参数

参数功能
-F指定输入时用到的字段分隔符
-v自定义变量
-f从脚本中读取awk命令
-mval值设置内在限制

常用的awk内置变量

awk语法由一系列条件和动作组成,在花括号内可以有多个动作,多个动作之间用分号分隔,在多个条件和动作之间可以有若干空格,也可以没有。

变量名称说明
FILENAME当前输入文档的文件名
FNR当前输入文档的当前行号,尤其当多个输入文档时有用
FS设置字段分隔符,默认为空格或制表符
NF当前记录(行)的字段(列)个数
NR输入数据流的当前记录数(行号)
OFS输出字段分隔符,默认为空格
ORS输出记录分隔符,默认为换行符
RS输入记录分隔符,默认为换行符

awk是一种处理文本文件的编程语言,文件的每行数据都被称为记录默认以空格或制表符为分隔符每条记录被分成若干字段(列)awk每次从文件中读取一条记录

例子:

  1. 仅显示指定文件中第1、2列的内容(默认以空格为间隔符):
lucky@DESKTOP-VQ8KID4:~/shell$ awk '{print $1,$2}' nowcoder.txt
#include <iostream>
using namespace
int main()
{
int a
int b
cout <<
return 0;
}
  1. 以冒号为间隔符,仅显示指定文件中第1列的内容:
lucky@DESKTOP-VQ8KID4:~/shell$ awk -F : '{print $1,$2}' /etc/passwd
root x
daemon x
bin x
...
tcpdump x
sshd x
landscape x
pollinate x
lucky x

/etc/passwd文件中的内容由:分隔开。

  1. 以冒号为间隔符,显示系统中所有UID号码大于500的用户信息(第3列):
lucky@DESKTOP-VQ8KID4:~/shell$ awk -F : '$3>=500' /etc/passwd
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
lucky:x:1000:1000:,,,:/home/lucky:/bin/bash
  1. 仅显示指定文件中含有指定关键词main的内容:
lucky@DESKTOP-VQ8KID4:~/shell$ awk '/main/{print}' nowcoder.txt
int main()
  1. 以冒号为间隔符,仅显示指定文件中最后一个字段的内容:
lucky@DESKTOP-VQ8KID4:~/shell$ awk -F : '{print $NF}' /etc/passwd
/bin/bash
/usr/sbin/nologin
/usr/sbin/nologin
...
/usr/sbin/nologin
/bin/false
/bin/bash
  1. 输出行号,NR将所有文件的数据视为一个数据流,而FNR则是将多个文件的数据视为独立的若干个数据流,遇到新文件时行号从1开始重新递增。
lucky@DESKTOP-VQ8KID4:~$ awk '{print NR}' first.txt three.sh
1
2
3
lucky@DESKTOP-VQ8KID4:~$ awk '{print FNR}' first.txt three.sh
1
1
2

grep:强大的文本搜索工具

grep来自于英文词组“global search regular expression and print out the line”的缩写,意思是用于全面搜索的正则表达式,并将结果输出。人们通常会将grep命令与正则表达式搭配使用,参数作为搜索过程中的补充或对输出结果的筛选,命令模式十分灵活。

与之容易混淆的是egrep命令和fgrep命令。如果把grep命令当作是标准搜索命令,那么egrep则是扩展搜索命令,等价于“grep -E”命令,支持扩展的正则表达式。而fgrep则是快速搜索命令,等价于“grep -F”命令,不支持正则表达式,直接按照字符串内容进行匹配。

语法格式: grep [参数] 文件

常用参数:

参数功能
-i忽略大小写
-c只输出匹配行的数量
-l只列出符合匹配的文件名,不列出具体的匹配行
-n列出所有的匹配行,显示行号
-h查询多文件时不显示文件名
-s不显示不存在、没有匹配文本的错误信息
-v显示不包含匹配文本的所有行
-w匹配整词
-x匹配整行
-r递归搜索
-q禁止输出任何结果,已退出状态表示搜索是否成功
-b打印匹配行距文件头部的偏移量,以字节为单位
-o-b结合使用,打印匹配的词据文件头部的偏移量,以字节为单位
-F匹配固定字符串的内容
-E支持扩展的正则表达式
  1. 搜索某个文件中,包含某个关键词的内容:
lucky@DESKTOP-VQ8KID4:~/shell$ grep root /etc/passwd
root:x:0:0:root:/root:/bin/bash
  1. 搜索某个文件中,以某个关键词开头的内容:
lucky@DESKTOP-VQ8KID4:~/shell$ grep ^root /etc/passwd
root:x:0:0:root:/root:/bin/bash
  1. 搜索多个文件中,包含某个关键词的内容:
root@DESKTOP-VQ8KID4:~# grep lucky /etc/passwd /etc/shadow
/etc/passwd:lucky:x:1000:1000:,,,:/home/lucky:/bin/bash
/etc/shadow:lucky:$6$SBxuPYFLSnBcfbHN$OkFFnnJCpf2P4OLOnnaWXMq.xbmgL3H5aRy4nkEkk/.8VHABaKDS6MdYm3UR3TpHZplAl5HVyffI8nbLlAAoh1:19256:0:99999:7:::
  1. 搜索多个文件中,包含某个关键词的内容,不显示文件名称:
root@DESKTOP-VQ8KID4:~# grep -h lucky /etc/passwd /etc/shadow
lucky:x:1000:1000:,,,:/home/lucky:/bin/bash
lucky:$6$SBxuPYFLSnBcfbHN$OkFFnnJCpf2P4OLOnnaWXMq.xbmgL3H5aRy4nkEkk/.8VHABaKDS6MdYm3UR3TpHZplAl5HVyffI8nbLlAAoh1:19256:0:99999:7:::
  1. 输出在某个文件中,包含某个关键词行的数量:
root@DESKTOP-VQ8KID4:~# grep -c root /etc/passwd /etc/shadow
/etc/passwd:1
/etc/shadow:1
  1. 搜索某个文件中,包含某个关键词位置的行号及内容:
lucky@DESKTOP-VQ8KID4:~/shell$ grep -n int nowcoder.txt
3:int main()
5:    int a = 10;
6:    int b = 100;
  1. 搜索某个文件中,不包含某个关键词的内容:
lucky@DESKTOP-VQ8KID4:~/shell$ grep -v int nowcoder.txt
#include <iostream>
using namespace std;
{
    cout << "a + b:" << a + b << endl;
    return 0;
}
  1. 搜索当前工作目录中,包含某个关键词内容的文件,未找到则提示:
root@DESKTOP-VQ8KID4:/# grep -l root *
grep: bin: Is a directory
grep: boot: Is a directory
grep: dev: Is a directory
grep: etc: Is a directory
grep: home: Is a directory
init
grep: lib: Is a directory
grep: lib32: Is a directory
...
grep: tmp: Is a directory
grep: usr: Is a directory
grep: var: Is a directory
  1. 搜索当前工作目录中,包含某个关键词内容的文件,未找到不提示:
lucky@DESKTOP-VQ8KID4:~/shell$ grep -sl main *
nowcoder.txt
  1. 递归搜索,不仅搜索指定目录,还搜索其内子目录内是否有关键词文件:
root@DESKTOP-VQ8KID4:/# grep -srl root /etc
/etc/services
/etc/ltrace.conf
/etc/systemd/logind.conf
/etc/crontab
/etc/newt/palette.ubuntu
/etc/xattr.conf
/etc/apparmor.d/tunables/home
...
  1. 搜索某个文件中,精准匹配到某个关键词的内容(搜索词应与整行内容完全一样才会显示,有别于一般搜索):
lucky@DESKTOP-VQ8KID4:~/shell$ grep -x "return 0;" nowcoder.txt
lucky@DESKTOP-VQ8KID4:~/shell$ grep -x "    return 0;" nowcoder.txt
    return 0;
  1. 判断某个文件中,是否包含某个关键词,通过返回状态值输出结果(0为包含,1为不包含),方便在Shell脚本中判断和调用:
lucky@DESKTOP-VQ8KID4:~/shell$ grep -q return nowcoder.txt
lucky@DESKTOP-VQ8KID4:~/shell$ echo $?  # 包含
0

lucky@DESKTOP-VQ8KID4:~/shell$ grep -q returns nowcoder.txt
lucky@DESKTOP-VQ8KID4:~/shell$ echo $?  # 不包含
1
  1. 搜索某个文件中,空行的数量:
lucky@DESKTOP-VQ8KID4:~/shell$ grep -c ^$ nowcoder.txt
0

wc:统计文件的字节数、单词数、行数

wc命令来自于英文词组“Word count”的缩写,其功能是用于统计文件的字节数、单词数、行数等信息,并将统计结果输出到终端界面。利用wc命令可以很快的计算出准确的单词数及行数,评估出文本的内容长度。

语法格式wc [参数] 文件

常用参数

参数功能
-w统计单词数
-c统计字节数
-l统计行数
-m统计字符数
-L显示最长行的长度
--help显示帮助信息
--version显示版本信息

统计指定文件的单词数量:

lucky@DESKTOP-VQ8KID4:~/shell$ wc -w nowcoder.txt
30 nowcoder.txt

统计指定文件的字节数量:

lucky@DESKTOP-VQ8KID4:~/shell$ wc -c nowcoder.txt
142 nowcoder.txt

统计指定文件的字符数量:

lucky@DESKTOP-VQ8KID4:~/shell$ wc -m nowcoder.txt
142 nowcoder.txt

统计指定文件的总行数:

lucky@DESKTOP-VQ8KID4:~/shell$ wc -l nowcoder.txt
9 nowcoder.txt

echo:输出字符串或提取后的变量值

echo是用于在终端设备上输出指定字符串或变量提取后值的命令,能够给用户一些简单的提醒信息,也可以将输出的指定字符串内容同管道符一起传递给后续命令作为标准输入信息再来进行二次处理,又或者同输出重定向符一起操作,将信息直接写入到文件中。
如需提取变量值,需在变量名称前加入$符号做提取,变量名称一般均为大写形式。

语法格式echo [参数] 字符串/变量

常用参数

-n不输出结尾的换行符
-e "\\a"发出警告音
-e "\\b"删除前面的一个字符
-e "\\c"结尾不加换行符
-e "\\f"换行,光标扔停留在原来的坐标位置
-e "\\n"换行,光标移至行首
-e "\\r"光标移至行首,但不换行
-E禁止反斜杠转移,与-e参数功能相反

参考实例

  1. 输出指定字符串到终端设备界面(默认为电脑屏幕):
wz@lucky:~$ echo hello world
hello world
  1. 输出某个变量值内容:
wz@lucky:~$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
  1. 搭配转义符一起使用,输出纯字符串内容:
wz@lucky:~$ echo \$PATH
$PATH
  1. 搭配输出重定向符一起使用,将字符串内容直接写入文件中:
wz@lucky:~$ echo Hello World > hello.txt
wz@lucky:~$ cat hello.txt 
Hello World
  1. 搭配反引号执行命令,并将执行结果输出:
wz@lucky:~$ echo `uptime`
19:41:45 up 7 min, 1 user, load average: 0.17, 0.54, 0.37
  1. 输出带有换行符的内容:
wz@lucky:~$ echo -e "One\nTwo\nThree"
One
Two
Three
  1. 指定删除字符串中某些字符,随后将内容输出:
wz@lucky:~$ echo -e "123\b456"
12456

题目解决方案

方法一:grep+awk

既然要求三个值,我们得把需要的数据先提取出来才行。

lucky@LAPTOP-G2DIO3FV:~$ awk -F"[ :]+" '/3306/{print $6, $8}' nowcoder.txt
172.16.34.144 ESTABLISHED
172.16.0.24 ESTABLISHED
172.16.0.24 ESTABLISHED
172.16.34.143 ESTABLISHED
172.16.0.24 ESTABLISHED
172.16.0.24 ESTABLISHED
172.16.34.144 ESTABLISHED
172.16.34.144 ESTABLISHED
172.16.34.144 ESTABLISHED
172.16.34.144 ESTABLISHED
172.16.0.24 ESTABLISHED
172.16.34.144 ESTABLISHED
172.16.0.24 ESTABLISHED
172.16.0.24 ESTABLISHED
172.16.0.24 ESTABLISHED
172.16.0.24 ESTABLISHED
172.16.34.144 ESTABLISHED
172.16.34.144 ESTABLISHED
172.16.0.24 ESTABLISHED
172.16.34.144 ESTABLISHED

这是31题我们讲过得分割方法,可以倒回去复习一下,这里就不多说啦。

把数据提取出来之后呢?我们来分析一下要求的三个值:

  1. TOTAL_LINK最简单,直接求数据得行数即可,这个用awk命令得NR就能得出。
  2. TOTAL_IP呢?要求建立连接的ip数目,仔细想想,这不就跟之前做了好多道题那样,直接用数组计数就行了。
  3. ESTABLISHED同理。

那么,很简单了,我们用awk命令就可以完全搞定这三个值的计算了。

awk -F"[ :]+" '/3306/{print $6, $8}' nowcoder.txt | awk -v establish=0 '{if($2=="ESTABLISHED"){establish++;};a[$1]=0} END{print "TOTAL_IP",length(a);print "ESTABLISHED",establish;print "TOTAL_LINK",NR}'

批注:

  • 这里定义的变量establish是拿来计算ESTABLISHED值的;
  • 数组a则是拿来计算IP个数的,为啥用数组呢?因为用数组既可以去重,还可以计数!去重不难理解吧?计数,直接用length(a)不就计算出IP个数了吗~
  • TOTAL_LINK不说了,一个NR就完事~

完整代码如下:(做了适当缩进,方便阅读)

awk -F"[ :]+" '/3306/{
	print $6,$8
}' nowcoder.txt | awk -v establish=0 '{
	if($2=="ESTABLISHED"){
		establish++
	}
	a[$1]=0
} END {
	print "TOTAL_IP", length(a)
	print "ESTABLISHED", establish
	print "TOTAL_LINK", NR
}'

题目看起来很难,其实也就那样…做题时注意一步一步分解。

方法二:awk

一个awk就可以搞定啦!代码如下:

awk '{
    if($1=="tcp" && $5 ~ "3306"){
        if ($6=="ESTABLISHED") {
            state++
        }
        ip[$5]++
        n++
    }
}END{
    print "TOTAL_IP " length(ip);
    print "ESTABLISHED " state
    print "TOTAL_LINK " n
}' nowcoder.txt

不详细说了,和上面的方法一其实类似,不一样的地方在于:

  • 这里使用awk命令的if来筛选出需要的数据
  • 此外,对于TOTAL_LINK的计算直接用一个递增的变量来计算的,换汤不换药呀。

方法三:grep+awk+wc(分步计算)

咱就是说,既然求的是三个值,如果前面的awk玩不转,那么一个一个值得计算,为啥不行呢?你说是吧~

  1. 首先来计算IP地址的个数,筛选出3306的行,利用数据进行计数即可:
lucky@LAPTOP-G2DIO3FV:~$ grep '[0-9]:3306' nowcoder.txt | awk -F" " '{a[$5]++} END{for(i in a) print a[i]}' | wc -l
3
  1. 计算状态为nESTABLISHED的个数,没啥好说的,看代码:
lucky@LAPTOP-G2DIO3FV:~$ grep '[0-9]:3306' nowcoder.txt | grep 'ESTABLISHED' | wc -l
20
  1. 计算连接数,更简单,看代码即可:
lucky@LAPTOP-G2DIO3FV:~$ grep '[0-9]:3306' nowcoder.txt | wc -l
20

分别把这三个值用变量存起来,然后用echo按要求输出即可。最终代码如下:

establish=$(grep '[0-9]:3306' nowcoder.txt | grep 'ESTABLISHED' | wc -l)
ip=$(grep '[0-9]:3306' nowcoder.txt | awk -F" " '{a[$5]++} END{for(i in a) print a[i]}' | wc -l)
link=$(grep '[0-9]:3306' nowcoder.txt | wc -l)
echo -e "TOTAL_IP "$ip "\nESTABLISHED "$establish"\nTOTAL_LINK "$link

定义变量的方式很多,你用````也是可以的,也即:

establish=`grep '[0-9]:3306' nowcoder.txt | grep 'ESTABLISHED' | wc -l`
ip=`grep '[0-9]:3306' nowcoder.txt | awk -F" " '{adi[$5]++} END{for(i in adi) print adi[i]}' | wc -l`
link=`grep '[0-9]:3306' nowcoder.txt | wc -l`
echo -e "TOTAL_IP "$ip "\nESTABLISHED "$establish"\nTOTAL_LINK "$link

方法四:纯Shell方法

逻辑一模一样,至于shell的语法这里就不多说了~

declare -A b
while read line; do
	a=($line)
	if [[ ${a[4]} =~ ^.*?3306$ ]]; then
		echo "TOTAL_LINK"
		if [[ ${a[5]} == "ESTABLISHED" ]]; then
			echo "ESTABLISHED"
		fi
		if [ -z ${b[${a[4]}]} ]; then
			echo "TOTAL_IP"
			let b[${a[4]}]=1
		fi
	fi
done <nowcoder.txt | sort | uniq -c | awk '{print $2" "$1}' | sort -nk2
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奋斗的西瓜瓜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值