标签:shell 面试题 开发 awk sed

原创作品,允许转载,转载时请务必以超链接形式标明文章  原始出处 、作者信息和本声明。否则将追究法律责任。 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]}
篇幅有限,不能全部列出,后面还会不断有内容更新。欢迎批评指教,不详之处,务请见谅!
 
 
 
 

本文出自 “林肯” 博客,请务必保留此出处http://president.blog.51cto.com/4990508/851407