Shell编程练习题精选及答案

来源:互联网 发布:印度军事实力 知乎 编辑:程序博客网 时间:2024/05/27 14:12
这里四道shell的面试题,学习shell的童鞋用来练手很不错。
前三道比较简单,都是对文件内容进行,按要求输出结果。用sed,awk,while-read以及here document和regex即可实现。
难点和重点在第四道题,算法性比较强。可以使用多个循环实现的很简单,但效率会很低。环的数字很多时,要很长时间才能运算完成。这里通过一步步的改进算法,做到了性能最优。代码改进过程中用到了shell调试的一些技能,如shell x选项,trap, PS4等。

========== 题目一 =============
文件内容:
100
a         100
b         -50
c         -20
d         -30
要求输出:
100
a          100
200
b          -50
150
c           -20
130
d          -30
代码:
#!/usr/bin/env bash# author: liguo# sumary: ex01.sh  awk -F$'\t' '{if(NR==1){sum=$1;next; }print sum;print $0;sum+=$2;}' << EOF100a100b-50c-20d-30EOF
========== 题目二 =============
文件内容:
123abc456
456def123
567abc789
789def567
要求输出:
456ABC123
123DEF456
789ABC567
567DEF789
代码:
#!/usr/bin/env bash# author: liguo# sumary: ex02.shwhile read line;doecho $line | tr [:lower:] [:upper:] | sed -r 's/([0-9]{3})([A-Z]{3})([0-9]{3})/\3\2\1/' done << EOF123abc456456def123567abc789789def567EOF
===============题目三=============
文件内容:
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

要求输出:
1.1.1.1       11  22  33  44
2.2.2.2       11  22  33  44

awk实现代码:
#!/usr/bin/env bash# author: liguo# sumary: ex03.sh{awk '{aa[$1]=length(aa[$1])>0 ? aa[$1]" "$2 : $2;}END {for(i in aa){print i"\t"aa[i];}}'<< EOF1.1.1.1 111.1.1.1 221.1.1.1 331.1.1.1 442.2.2.2 112.2.2.2 222.2.2.2 332.2.2.2 44EOF} | sort # lines output by descending by default, sort it by ascending here.

sed实现代码:
#!/usr/bin/env bash# author: liguo# sumary: ex03b.sh# use variables to generate long regex for sed, let code more readablekey="([0-9\.]{7})"sps="[[:space:]]+"val="([0-9]{2})"lne="$key$sps$val"re="$lne$sps$lne$sps$lne$sps$lne"sed -r "N;N;N;s/\n/ /g;s/$re/\1 \2 \4 \6 \8/g" << EOF1.1.1.1 11 1.1.1.1 221.1.1.1 331.1.1.1 442.2.2.2 11 2.2.2.2 222.2.2.2 332.2.2.2 44EOF
===========题目四=======
有1到100的数字序列围成一个环。计数器从1开始数,每数到12的整数倍,就将计数器指向的数字从环中剔除,问该环中最后剩下的数字是多少?100结果为81

代码:为了保证数字序列长度很大时, 程序的执行效率,对代码进行了多次优化,比如只用使用了一个循环;环中数字被移除后,左移后面的数字,减小序列,避免扫描数组空位置;防止数字溢出等。
#!/usr/bin/env bash
# author: liguo# summary: ex05.sh# usage: 0x05.sh [number]# example: #bash ex05.sh 10000#The final left number is: 6746# open debug options #set -x#export PS4="+[$LINENO:${FUNCNAME[0]}]"#trap 'echo "n1=$n1, n2=$n2, n3=$n3, ni=$ni, aa[y-n3]=${aa[$[y-n3]]}, aa[y]=${aa[$y]}, y=$y"' DEBUG# validate number count of the last outter loopif [[ $1 =~ ^[0-9]+$ ]];then # test if $1 is a valid number.n0=$1elsen1=100filet n1=n0 # the outter loop index uplimit of the outter looplet n2=n1 # real time valid number countlet ni=0 # the counter, we need it to increases without restore to 1. But variable i will do.for ((i=1;n1>1;i=i%n1+1));dolet ni++if [ $[ni%12] -eq 0 ];thenlet aa[i]=0let n2--let n3=n1-n2# when n0 is large value, ni will be very large,# it's very possible to overflow. So reset it to 0, it will more easy to calculate ni%12 too. let ni=0 elif ((n1==n0));then # if it is the firt time of the  out loop, fill array aa with value i.let aa[i]=ifiif ((n2<n1 && aa[i]!=0));then# remove some number that at the position of 12*n, now move later array elements left # to fill these empty positons. Then it will loop fewer positions after loop index i restore to 1. # This is important when variable n0 is a large number, such as 1000,000if ((n3>0));thenlet aa[i-n3]=aa[i]fifi# make i==n1, ensure outter loop index 'i' restart from 1 after operation 'i=i%n1+1'if ((i==n1 && n2<n1));thenlet n1=n2let i=n1 let n3=0fidoneecho "The final left number is: ${aa[$n1]}"# close debug options#set +x#export PS4="+"

0 0
原创粉丝点击