原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。 http://president.blog.51cto.com/4990508/851407
由于工作的关系,收集了很多的shell面试题,有些比较有意思,有些纯粹是为折磨人用的题目。有的看完会心一笑,有的看了之后会以为是几年前开发的面试题。不知道是会的人多了,还是有意的为难,想起一句话,庙小妖风大,水浅那个啥多。
多说一句,解决的方法有很多种,也许这里给出的答案并不是最优的,但应该是比较容易解释,容易理解的。具体是什么公司的面试题就不说了,毕竟是人家的隐私。
一 文件内容如下:
100
a 100
b -50
c -20
d -30
要求输出结果为:
100
a 100
200
b -50
150
c -20
130
d -30
一句话思路:用shell肯定是不行,因为是操作文件。用sed倒是可以操作文件,但有数学运算还要用到变量。所以,用awk应该是最好的。
awk 'NR==1{sum=$1;print $0}NR!=1{print $0;sum=sum-$2;print sum}' 内容文件
知识点:awk变量,域
二 文件内容如下:
123abc456
456def123
567abc789
789def567
要求输出:
456ABC123
123DEF456
789ABC567
567DEF789
一句话思路:以点带面,文字处理,shell不行,awk不行,用sed加正则表达式
sed -r 's/([1-9]{3})([a-f]{3})([1-9]{3})/\3\2\1/;y/abcdef/ABCDEF/' 内容文件
知识点:-r 支持扩展的正则表达式,跟grep用-P类似。y其实就是tr只是写到sed里面更好看一些,sed的查找替换,当然还有正则中的分组。sed中的分组可以这么用,awk就不行了只能用&,而且分组数量不能超过9,即不会有\10出现。
三. 文件内容如下
1.1.1.1 11
1.1.1.1 22
1.1.1.1 33
1.1.1.1 44
2.2.2.2 11
2.2.2.2 22
2.2.2.2 33
2.2.2.2 44
要求使用sed及awk分别将文件输出:
1.1.1.1 11 22 33 44
2.2.2.2 11 22 33 44
一句话思路:这个没啥思路了,上面还分析分析用什么合适,这里面没的选了,人家都说了,就弄吧。
sed -r 'N;N;N;s/\n/ /g;s/(.*)(11 )(.*)(22 )(.*)(33 )(.*)(44)/\1\2\4\6\8/' 内容文件
知识点:N将文件的下一行读入模式空间,3个N就是读取下面三行进入当前模式空间,读进去的行依然保留换行,所以删除换行,后面的就不说了,你懂的。
awk '{sum[$1]=sum[$1]" "$2}END{for(var in sum)print var sum[var]}' 内容文件
知识点:awk数组,awk字符串赋值,使用for遍历awk数组。
四. 分析apache日志,给出当日访问ip的降序列表。
一句话思路:分析ip就要提取ip,提取的办法除了awk,还有个东西叫cut。
cut -d " " -f1 /etc/httpd/log/access_log | sort | uniq -c | sort -nr
知识点:cut命令,sort将汇总相同内容,uniq -c合并重复内容,并给出重复次数。sort -nr 使用数字排序,默认是ascii,并且是降序,默认是升序。
awk '{sum[ip]++}END{for(var in sum)print ip sum[var]}' /etc/httpd/log/access_log | sort -k2 -nr
知识点:awk数据,sort -k2 -nr 降序数字排序就不说了,-k参数指定使用哪个列进行排序。默认是自然是第一列。
五.亚瑟王环
有1到100的数字序列。有计数器每数到12,就将计数器指向的数字在亚瑟环中剔除,问该序列中最后剩下的数字是多少?
一句话思路:100,12的太复杂,就弄个10,2的,完成之后替换一下。。。。。。
最后的答案是:81 面试的时候你可以说是心算的(别脱口而出,稍微伪装一下),就是不知道行不行。
做计数器,当计数器到达12的时候就将一个数组中对应的值赋值为零。当所有数组中的数字还剩唯一的不为零的值的时候就是剩下的数字。
#/bin/bash
for i in {1..100};do
huan[$i]=$i
done #先初始化一个数组,其实用变量也行,个人喜好,用awk也行,但一篇内容一个shell有点不合适。
t=0 #定义一个计数器
sum=0
while true;do #定义一个无限循环,因为确实不知道要数多少次。
for((i=1;i<101;i++));do
if [ ${huan[$i]} -gt 0 ];then #不等于零就把计数器加1
let t++
fi
if [ $t -eq 12 ];then #数到12就将数组中的数清零,同时计数器清零
huan[$i]=0
t=0
fi
done
for((i=1;i<101;i++));do #遍历数组,如果数组中只有一个数不为零就跳出循环
if [ ${huan[$i]} -gt 0 ];then
let sum++
sum[1]=${huan[$i]}
fi
done
if [ $sum -eq 1 ];then
break
else
sum=0
fi
done
echo ${sum[1]}
篇幅有限,不能全部列出,后面还会不断有内容更新。欢迎批评指教,不详之处,务请见谅!