牛客shell题_刷题笔记
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
areand
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,输出整行