Linux编程题

前言

Linux现在是服务器的首选,于是日常工作中shell命令必不可少!二刷shell,简单总结了一下,希望对君有所帮助。

简单总结

shell相关题,以grep、awk、sed三剑客为主,外加sort、uniq、wc这些命令为辅,以一些显示命令cat、head、tail、less、more来展示。
熟练运用好常用命令,并不断地去学习和练习正则表达式,我们都可以快速地将玩转shell !

统计文件的行数

写一个 bash脚本以输出一个文本文件 nowcoder.txt中的行数
示例:
假设 nowcoder.txt 内容如下:

复制代码

#include <iostream>``using` `namespace` `std;``int` `main()``{``  ``int` `a = 10;``  ``int` `b = 100;``  ``cout << ``"a + b:"` `<< a + b << endl;``  ``return` `0;``}

你的脚本应当输出:
9

#解法1:awk
awk '{print NR}'| tail -n1
#awk print NR 打印每一行的行号
#tail -n1 只打印最后一行

#解法2:awk
awk 'END{print NR}'
#awk END{print NR} 最后打印行号
#关于 awk 脚本,我们需要注意两个关键词 BEGIN 和 END。
#BEGIN{ 这里面放的是执行前的语句}
#{这里面放的是处理每一行时要执行的语句}
#END {这里面放的是处理完所有的行后要执行的语句 }

#解法3:wc
wc -l
# wc -l 统计文件有多少行
# wc -wcl  -w word多少单词 -c char 多少字符 -l line 多少行

#解法4:sed
sed -n '$='
# -n或--quiet或--silent 仅显示script处理后的结果。
# 正则表达式中   行尾定位符“$” 行首定位符“^” 

#解法5:grep
grep -n "" |tail -n1| awk -F: '{print $1}'
# grep -n ""  -n显示行号, 匹配"" 即显示每一行的行号
# awk -F:    只取第一列,即行号,以:分割
# tail -n1   只取最后一行,即总行数

#解法6:cat
cat -n |tail -1|awk '{print $1}'
# cat -n   显示每一行,并添加上行号
# tail -1  只取最后一行,即总行数
# awk -F   只取第一列,即行号,默认空格分隔

打印文件的最后5行

​ 题目描述

经常查看日志的时候,会从文件的末尾往前查看,于是请你写一个 bash脚本以输出一个文本文件 nowcoder.txt中的最后5行
示例:
假设 nowcoder.txt 内容如下:

#include<iostream>``using` `namespace` `std;``int` `main()``{``int` `a = 10;``int` `b = 100;``cout << ``"a + b:"` `<< a + b << endl;``return` `0;``}

你的脚本应当输出:

int` `a = 10;``int` `b = 100;``cout << ``"a + b:"` `<< a + b << endl;``return` `0;``}
#解法1:
tail -5 
#tail 从后往前看文件, -5 只看5行
# -f 循环读取,实时读取文件  -n 读多少行 只用-n n可以省略

输出7的倍数

​ 题目描述

写一个 bash脚本以输出数字 0 到 500 中 7 的倍数(0 7 14 21...)的命令

#解法1:循环
for i in {0..500..7}
do
    echo $i
    done    
# 新建变量i,做一个循环,从0到500,每间隔7次,打印一次i

#解法2:seq
seq 0 7 500
# seq 用于生成从一个数到另一个数之间的所有整数。
# 用法:seq [选项]... 尾数
# 或:seq [选项]... 首数 尾数
# 或:seq [选项]... 首数 增量 尾数

输出第5行的内容

题目描述

写一个 bash脚本以输出一个文本文件 nowcoder.txt 中第5行的内容。

示例:
假设 nowcoder.txt 内容如下:
welcome
to
nowcoder
this
is
shell
code

你的脚本应当输出:
is

#解法1:sed
sed -n '5p' 
# -n或--quiet或--silent 仅显示script处理后的结果。
#sed -n '5,7p'  仅列出文件内的第 5-7 行

#解法2: head + tail
head -n 5 | tail -n 1
# head 从头往尾部看,并显示
# tail 从尾部往头看,并显示
#先显示前5行,再从后往前显示一行

#解法3: awk
awk 'NR==5'
# awk NR==5 只显示第5行的内容,因为没有{print}去限制显示第几列,默认显示全部,即$0;

#解法4: cat + grep + awk
cat -n |grep 5|awk '{print $2}'
#cat -n 显示每一行,并添加上行号
#grep 5 找到第5行,如果文件内容存在5,会出错;该题只有字母所以不会
#awk  显示想要显示的列

打印空行的行号

题目描述

写一个 bash脚本以输出一个文本文件 nowcoder.txt中空行的行号,可能连续,从1开始

示例:
假设 nowcoder.txt 内容如下:

a``b` `c` `d` `e` `f

你的脚本应当输出:
3
5
7
9
10

#解法1:sed
 sed -n '/^$/=' 
# -n或--quiet或--silent 仅显示script处理后的结果。
#sed -n '/^$/='  按正则匹配空行,并打印行号;
#正则表达式中  行首定位符“^” 行尾定位符“$”  "^$"表示空,即直接首尾

#解法2:awk
awk '/^$/ {print NR}'
# 按正则匹配空行,并打印行号;{print NR} 打印行号
# 正则表达式中  行首定位符“^” 行尾定位符“$”  "^$"表示空,即直接首尾

#解法3: grep + sed
grep -n "^$" |sed  's/\://g'
#利用grep查找空行并打印(有冒号)
#用sed把冒号替换成空后,打印

#解法4: grep + awk
grep -n "^$" |awk -F : '{print $1}'
#利用grep查找空行并打印(有冒号),
#awk 打印第一列,以':'分割

去掉空行

题目描述

写一个 bash脚本以去掉一个文本文件 nowcoder.txt中的空行
示例:
假设 nowcoder.txt 内容如下:

abc` `567` `aaa``bbb`  `ccc

你的脚本应当输出:
abc
567
aaa
bbb
ccc

#解法1: sed
sed -n '/[^$]/p'
#sed -n 静默模式
#p:打印变动的流(行)
#正则部分: [^$] ^代表以后面跟着的字符为开头,$代表以前面的字符为结尾;
#^$联合使用,中间不加任何字符数字,代表匹配空行;
#[ ] 在shell正则中表示取反

#解法2:sed
sed '/^$/d' 
#sed 先匹配空行,然后删除空行d 即delete ;最后打印

#解法3:grep
grep -v -E '^$'
#grep -v 取反,即匹配不上的
#-E (等效于egrep) 可以匹配正则表达式

#解法4:awk
awk '!/^$/ {print $NF}'
#$n    当前记录的第n个字段,字段间由FS分隔
#NF    一条记录的字段的数目
#NR    已经读出的记录数,就是行号,从1开始

打印字母数小于8的单词

题目描述

写一个 bash脚本以统计一个文本文件 nowcoder.txt中字母数小于8的单词。

示例:
假设 nowcoder.txt 内容如下:
how they are implemented and applied in computer

你的脚本应当输出:
how
they
are

and

applied

in

说明:
不要担心你输出的空格以及换行的问题

#解法1:awk
awk '{
for (i=1;i<=NF;i++){
        if (length($i) < 8)
                print $i
}
}'
#通过awk去读每一个单词,当字母数小于8,打印


#解法2:tr + awk
tr " " "\n" | awk '/^.{0,7}$/'
#先通过tr,将行转化成列,(即空格转换为 换行符)
#再显示字母数小于8的行;(用正则)


#解法3:awk
awk 'BEGIN{FS="";RS=" ";ORS="\n"}{if(NF<8)print$0}' 
#awk 分隔符记忆
#FS  字段分隔符(默认是任何空格) 
#RS  记录分隔符(默认是一个换行符)
#ORS 输出记录分隔符(默认值是一个换行符) 
#将列转为行,再输出字母数小于8的行

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

题目描述

假设 nowcoder.txt 内容如下:
root 2 0.0 0.0 0 0 ? S 9月25 0:00 [kthreadd]
root 4 0.0 0.0 0 0 ? I< 9月25 0:00 [kworker/0:0H]
web 1638 1.8 1.8 6311352 612400 ? Sl 10月16 21:52 test
web 1639 2.0 1.8 6311352 612401 ? Sl 10月16 21:52 test
tangmiao-pc 5336 0.0 1.4 9100240 238544 ?? S 3:09下午 0:31.70 /Applications

以上内容是通过ps aux | grep -v 'RSS TTY' 命令输出到nowcoder.txt文件下面的
请你写一个脚本计算一下所有进程占用内存大小的和:

awk '{sum+=$6} END{print sum}'

#首先通过题意知道第六列是内存信息列
#通过sum变量将每行的第六列相加统计,最后输出

统计每个单词出现的个数

题目描述

写一个 bash脚本以统计一个文本文件 nowcoder.txt 中每个单词出现的个数。

为了简单起见,你可以假设:
nowcoder.txt只包括小写字母和空格。
每个单词只由小写字母组成。
单词间由一个或多个空格字符分隔。

示例:
假设 nowcoder.txt 内容如下:
welcome nowcoder
welcome to nowcoder
nowcoder
你的脚本应当输出(以词频升序排列):
to 1
welcome 2
nowcoder 3

说明:
不要担心个数相同的单词的排序问题,每个单词出现的个数都是唯一的。

#解法1: 
cat $1  | tr -s ' ' '\n' |sort |uniq -c|sort | awk '{print $2" "$1}' 
# cat 查看全部 
#tr -s  将' '转化为 换行
#sort 排序
#uniq -c 统计行出现次数(需要先排序)
#sort 再排序,按升序显示
#awk 改变显示方式

#解法2:
awk '{for(i=1;i<=NF;i++)a[$i]++} END{for (i in a){print i,a[i]}}'
#awk + 计数排序
#将每一个单词对应的次数相加,最后输出所有的单词和出现次数

第二列是否有重复

题目描述

给定一个 nowcoder.txt文件,其中有3列信息,如下实例,编写一个sheel脚本来检查文件第二列是否有重复,且有几个重复,并提取出重复的行的第二列信息:
实例:
20201001 python 99
20201002 go 80
20201002 c++ 88
20201003 php 77
20201001 go 88
20201005 shell 89
20201006 java 70
20201008 c 100
20201007 java 88
20201006 go 97

结果:
2 java
3 go

awk '{print $2}' nowcoder.txt|sort|uniq -cd|sort -n
# awk 先筛选出第二列
# sort 排序
# uniq -cd    -c统计每行行数 -d只显示重复行
# 再次排序按升序显示信息

转置文件的内容

写一个 bash脚本来转置文本文件nowcoder.txt中的文件内容。

为了简单起见,你可以假设:
你可以假设每行列数相同,并且每个字段由空格分隔

示例:
假设 nowcoder.txt 内容如下:
job salary
c++ 13
java 14
php 12

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

#解法1:
awk '{printf $1}' nowcoder.txt
awk '{printf $2}' nowcoder.txt
#先输出第一列,再输出第二列

#解法2:
awk '{
    for(i=1;i<=NF;i++){rows[i]=rows[i]" "$i}
} END{
    for(line in rows){print rows[line]}
}' 
#第一个式子将每一列存到了一个行数组里
#第二个式子  END最终,输出行数组

打印每一行出现的数字次数

题目描述

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

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

sed s/[^1-5]//g  |awk '{a+=length($0);printf("line%d number: %d\n",NR,length($0))} END{printf("sum is %d",a)}'

#sed 将1-5之外的字符全替换为空,即只保留'1到5';
#awk 先统计每一行还剩下多少长度,并用a将每行长度累加
#先打印每行还剩多少长度(字符),行号+字符数 即NR,length($0)
#最后打印整体的字符长度 a

去掉所有包含this的句子

题目描述

写一个 bash脚本以实现一个需求,去掉输入中含有this的语句,把不含this的语句输出
示例:
假设输入如下:
that is your bag
is this your bag?
to the degree or extent indicated.
there was a court case resulting from this incident
welcome to nowcoder

你的脚本获取以上输入应当输出:
to the degree or extent indicated.
welcome to nowcoder

说明:
你可以不用在意输出的格式,包括空格和换行

#解法1: grep
grep -v "this" 
#匹配所有不含this的行


#解法2:sed
sed '/this/d'
#将所有包含this的行删除,并显示


#解法3:awk
awk '$0!~/this/ {print $0}'
# !表示取反;~ 表示模式开始。// 中是模式。 
#比如: 输出第二列包含 "th",并打印第二列与第四列
# awk '$2 ~ /th/ {print $2,$4}' log.txt

求平均值

​ 题目描述

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

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

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

#解法1:
awk 'NR==1{all=$0} NR>1{total+=$0} END{printf "%.3f" ,total/all}'
# 将第一行读为长度,将其他行作为数值求和
# 最后将和/长度,格式化小数点后三位输出

#解法2:(同1)
awk '{if(NR!=1)total+=$1} END{printf("%.3f\n",total/(NR-1))}'
# 除了第一行不读,将其他行作为数值求和
# 最后将  和/长度 (即:总行数-1),格式化小数点后三位输出

去掉不需要的单词

题目描述

写一个 bash脚本以实现一个需求,去掉输入中的含有B和b的单词
示例:
假设输入如下:
big
nowcoder
Betty
basic
test

你的脚本获取以上输入应当输出:
nowcoder test

说明:
你可以不用在意输出的格式,空格和换行都行

#解法1: grep
grep -iv "b"
#grep -i ignore 忽略大小写 -v invert 不匹配
#即显示不含B和b的

#解法2: sed
sed '/B\|b/d'
#等同于 
# sed '/b/d' | sed '/B/d' 
# d delete 删除,将包含b或B的行,删除

#解法3: awk
awk '$0!~/[bB]/ {print $0}'
# $0表示整行
# 不包含b或B,输出整行