目录
前言
所有的题尽量不用,tail、cat、grep、awk这种命令直接执行得出结果,全用bash shell语句编程,这样程序最高效
以下是我学Shell的方法,供参考
1、先花半天时间看下基本用法:Shell教程-菜鸟教程
注:如果你觉得直接看无聊,可以先花半天时间刷牛客前五题简单题,看看排行前几名写法,稍微就入门了一丢丢,然后再看菜鸟教程
2、再把牛客Shell题目花一天时间刷完,不会的看看排行里别人写的,尽量自己按思路,自己完成,一定自己思考,自己敲,别复制别人的运行,可以看别人思路,自己写,但别看一下写一下,大概总共花2天时间,shell编程基础点开发就没问题,多动手学得快,更深刻
自己思考完成20题,shell语法、基本编程就没啥问题,反正我是这么感觉的,集中时间刷完
题目
20道
1、统计文件行数
题目
描述
写一个 bash脚本以输出一个文本文件 nowcoder.txt中的行数
...
代码
while read val # 逐行读取,val即为每行
do
# 每读一行就+1,即自增
((line++))
done < ./nowcoder.txt # 每次完成就重定向到文件,继续读取,<表示重定向
echo $line
2、打印文件的最后5行
后面都直接上代码
#!/bin/bash
line=0
while read val
do
line=$((line+1))
done < nowcoder.txt
line=$((line-5))
cnt=0
while read val
do
if (($cnt >= $line )) # 相当于line前面的不输入,输入其后面的
then
echo $val
fi
cnt=$((cnt+1))
done < nowcoder.txt
3、输出7的倍数
for i in {0..500}
do
if (( i % 7 == 0))
then
echo $i
fi
done
4、输出第5行的内容
#!bin/bash
num=1
while read line
do
if ((num == 5))
then
echo $line
fi
((num++))
done < nowcoder.txt
5、打印空行的行号
#!/bin/bash
num=1
while read line
do
if [ -z $line ]
then
echo $num
fi
((num++))
done < nowcoder.txt
6、去掉空行
#!/bin/bash
while read line
do
if [ -z $line ]
then
continue
else
echo $line
fi
done < nowcoder.txt
7、打印字母数小于8的单词
# 思路1:先分割存入数组,然后分别统计
# 思路2:遍历字符串,num=0,遇到空格就判断,看是否可以输出
#!/bin/bash
read line < nowcoder.txt # 读nowcoder.txt一行
for n in $line
do
if [ "${#n}" -lt 8 ]
then
echo ${n}
fi
done
8、统计所有进程占用内存大小的和
# 读取每行,然后获取第二列值,将其相加
sum=0
while read line
do
arr=($line)
((sum+=arr[5]))
done < nowcoder.txt
echo $sum
9、 统计每个单词出现的个数
典型题,去重、统计个数都一样的
# 解题步骤:
# 1、逐行读取,每一行的单词存到map中,相当于一个初始化过程
# 2、用一个数组存去重后的单词出现次数
# 3、冒泡排序
# 4、将排序后的次数与map中的value对比,相等就依次输出,这样就是排序后的
declare -A map
while read line
do
arr=$line
for i in ${arr[@]}
do
if [ -z ${map[$i]} ]
then
map[$i]=1
else
((map[$i]++))
fi
done
done < nowcoder.txt
mm=()
for value in ${map[@]}
do
mm[${#mm[@]}]=${value}
done
len=${#mm[@]}
for ((i=0;i<len;i++))
do
for ((j=i+1;j<len;j++))
do
if [ ${mm[$i]} -gt ${mm[$j]} ]
then
tmp=${mm[$i]}
mm[$i]=${mm[$j]}
mm[$j]=$tmp
fi
done
done
for ((k=0;k<len;k++))
do
for key in ${!map[@]}
do
if [ ${map[$key]} -eq ${mm[$k]} ]
then
echo $key ${map[$key]}
fi
done
done
10、第二列是否有重复
# 解题步骤
# 1、构造map,key-value为第2列元素-出现次数
# 2、将map中的元素出现次数放到数组中
# 3、对数组排序
# 4、按照排序顺序输出
declare -A map
# 第一步:构造map
while read -a line
do
key=${line[1]}
if [ -z ${map[${key}]} ]
then
map[${key}]=1
else
((map[${key}]++))
# echo $key ${map[${key}]}
fi
done < nowcoder.txt
# 第二步:将重复的元素次数放到数组中
arr=()
for key in ${!map[@]}
do
if [ ${map[$key]} -gt 1 ]
then
echo ${map[$key]} $key
arr[${#arr[@]}]=${map[$key]}
fi
done
# 第三步:对arr数组(出现次数)排序
len=${#arr{@}}
for (( i=0;i<len;i++ ))
do
for (( j=$[$i+1];j<len;j++ ))
do
if [ ${arr[$i]} -gt ${arr[$j]} ]
then
# 交换
tmp=${arr[$i]}
arr[$i]=${arr[$j]}
arr[$j]=$tmp
fi
done
done
#第四步:输出
for (( k=0;k<len;k++ ))
do
for key in ${!map[@]}
do
if [ ${map[${key}]} -eq ${arr[$k]} ]
then
echo ${map[$key]} ${key}
fi
done
done
11、转置文件的内容
# 读取每行,得出行数与列数,然后遍历,注意shell是没有二维数组的,只有一维
# 第一步:读取每行,放到数组中
arr=()
while read line
do
arr[${#arr[@]}]=$line
done < nowcoder.txt
# 第二步:转置输出,即行列调换遍历输出
rows=${#arr[@]}
m=(${arr[0]})
columns=${#m[@]}
for (( i=0;i<$columns;i++ ))
do
for (( j=0;j<$rows;j++ ))
do
tmp=(${arr[$j]})
echo "${tmp[$i]} "
done
done
12、打印每一行出现的数字个数
# 字符串截取、正则表达式
line_num=0 # 行号
sum=0 # 数字总数
while read line
do
count=0 # 记录每行的数字个数
((line_num++))
for (( i=0;i<${#line};i++ ))
do
if [[ ${line:$i:1} =~ [1-5] ]]
then
((count++))
fi
done
((sum+=count))
echo "line${line_num} number:${count}"
done < nowcoder.txt
echo "sum is ${sum}"
13、 去掉所有包含this的句子
# 读取每行,每行生成数组,看是否含this,有则continue,否则输出
while read line
do
flag=0
for i in $line
do
if [ $i == "this" ] # 注意==和-eq的区别,==比较字符串,-eq比较对应的值
then
flag=1
break
fi
done
if [ $flag -eq 0 ]
then
echo $line
fi
done < nowcoder.txt
14、求平均值
read len # 输入长度
loop_time=$len
sum=0
while (($loop_time > 0))
do
read ele
((sum+=ele))
((loop_time--))
done
echo "scale=3;$sum/$len" | bc # bc工具显示小数
15、去掉不需要的单词
# 读取输入
while read line
do
len=${#line}
flag=1
# 判断字符串的每个字符
for (( i=0;i<len;i++ ))
do
if [[ ${line:$i:1} == "B" || ${line:$i:1} == "b" ]]
then
flag=0
break
fi
done
if [ $flag -eq 1 ]
then
echo $line
fi
done
16、判断输入的是否为IP地址
# 有四位数字组成,且数字范围均在0~255之间
# Shell怎么做分隔?按.分隔,返回到数组,${parameter//pattern/string}
while read line
do
arr=(${line//./ })
len=${#arr[@]}
if [[ $len != 4 ]]
then
echo "error"
continue
fi
flag=1
for ele in ${arr[@]}
do
if [ $ele -ge 0 -a $ele -le 255 ]
then
continue
else
flag=0
break
fi
done
if [ $flag -eq 1 ]
then
echo "yes"
else
echo "no"
fi
done < nowcoder.txt
17、将字段逆序输出文件的每行
这里用awk会更快,更容易懂,我自己用shell语句写,不好写感觉
# NF表示一行有多少个单词,-F ":"表示按:分隔
awk -F ":" '{ for(i=NF;i>=1;i--)
if (i != 1){
{printf $i ":"}
} else {
{print $i}
}
}' nowcoder.txt
18、域名进行计数排序处理
# 这个就类似字符串重复次数,并排序
declare -A map
while read line
do
tmp=(${line//\// }) # 反斜杠转义
name=${map[${tmp[1]}]}
# echo $name
if [ -z $name ]
then
map[${tmp[1]}]=1
else
((map[${tmp[1]}]++))
fi
done < nowcoder.txt
# 构造数组
arr=()
for key in ${!map[@]}
do
arr[${#arr[@]}]=${map[$key]}
done
len=${#arr[@]}
# 对数组排序(降序), 用了冒泡
for (( i=0;i<len;i++ ))
do
for (( j=i+1;j<len;j++ ))
do
if [ ${arr[$i]} -lt ${arr[$j]} ]
then
tmp=${arr[$i]}
arr[$i]=${arr[$j]}
arr[$j]=$tmp
fi
done
done
# 按数组排序顺序输出
for (( k=0;k<len;k++ ))
do
for key in ${!map[@]}
do
if [ ${map[${key}]} -eq ${arr[$k]} ]
then
echo ${map[$key]} ${key}
fi
done
done
19、打印等腰三角形
记得是最开始学C语言,课本习题就是这个
for (( i=1;i<=5;i++ ))
do
# 打印空格
for (( j=5-i;j>=1;j-- ))
do
printf " "
done
# 打印星星
for (( k=1;k<=i;k++ ))
do
printf "* "
done
printf "\n"
done
20、打印只有一个数字的行
while read line
do
count=0
for (( i=0;i<${#line};i++ ))
do
if [[ ${line:$i:1} =~ [0-9] ]]
then
((count++))
fi
done
if [ $count -eq 1 ]
then
echo $line
fi
done < nowcoder.txt