前言
练习三剑客,题目来源于牛客的shell在线练习
这里仅显示我认为比较有难度的
实践
1.写一个bash脚本,统计一个文本文件nowcoder.txt中每一行出现的1~5数字的个数,并且计算一下整个文档中一共出现了几个1~5数字的总数
cat nowcoder.txt|sed 's/[a-zA-Z]//g'|awk 'BEGIN{FS="";sum=0;}{
num=0;
for(i=1;i<=NF;i++){
if($i>=1&&$i<=5){
num++
}
}
sum+=num;
print "line"NR,"number:"num
}END{
print "sum is"sum
}'
刚开始接触这种负载的awk,没写出来,这是借鉴大佬的
因为需要格式化输出,并且最后需要总结,第一个想到了awk,但是要求数字范围为1-5,所以先使用sed过滤
原本考虑使用tr但是tr无法使用正则,其实这里后来想想不需要使用sed过滤因为awk无法对字符格式的进行数值计算所以会直接跳过
awk流程:
1.因为需要对每个数字单独进行匹配而awk默认只能按照列匹配,所以在BEGIN初始化,设置FS按字符分列,使每个字符一列
2.行处理,每一行计算数字的数量,结束后输出并汇集到sum中
3.END最终输出sum
2.写一个bash脚本以实现一个需求,求输入的一个数组的平均值
第1行为输入的数组长度N
第2~N行为数组的元素
awk 'BEGIN{
sum=0;
max=0
}{
if(NR==1){
max=$1
}else{
sum+=$1
}
}END{
#print sum/max 精度太高不符合
printf "%.3f\n",sum/max
}'
手撕
第一行获取除数,行内计算获取被除数,最后在END格式化输出
3.写一个bash脚本以实现一个需求,去掉输入中含有B和b的单词
#一个错误的想法
awk '/[^bB]/{print}'
#这里想输出不含b或B的行,但是却完整输出了,因为想法是错的,实际上只要有不是b或B就输出,就是即使有bB但有其他字符也会输出awk '{
for (i=1; i<=NF; i++) {
if ($i ~ /.*[bB]+.*/) {
continue
} else {
print $i
}
}
}'4.写一个脚本统计文件nowcoder.txt中的每一行是否是正确的IP地址。
如果是正确的IP地址输出:yes
如果是错误的IP地址,且是四段号码的话输出:no,否则的话输出:error
NF是该行的列数,$NF是该行的最后一列
awk -F '.' '{
if(NF!=4){
print "error"
} else{
sign=0;
for (i=1;i<=4;i++){
if ($i <=255){
contiue;
}else{
sign=1;
break;
}
}
if (sign==0){
print "yes"
}else{
print "no"
}
}
}' nowcoder.txt
首先判断是否是4段号码,否则直接error,其次再通过对每个字段的内容判断是否符合IP形式
5.将文件nowcoder.txt中每一行的字段逆序输出,其中字段之间使用英文冒号:相分隔。
假设nowcoder.txt内容如下:
nobody:*:-2:-2:Unprivileged User:/var/empty:/usr/bin/false
root:*:0:0:System Administrator:/var/root:/bin/sh
#print默认会换行,printf默认不会换行
awk 'BEGIN{
FS=":";OFS=":"
}{
for(i=NF;i>0;i--){
printf $i
if(i!=1){
printf ":"
}
}
print '\n'
}'发现其中的OFS其实是没有用的,其原因是OFS只有在print $1,$2,$3 连续输出时才会有用
6.假设有一些域名,存储在nowcoder.txt里,现在需要写一个shell脚本,将域名取出并根据域名进行计数排序处理(降序)。
假设nowcoder.txt内容如下:
http://www.nowcoder.com/index.html
http://www.nowcoder.com/1.html
http://m.nowcoder.com/index.html
cat nowcoder.txt|grep -oP '(?<=http://)\S+\.\S+\.(com|cn|io)' |sort |uniq -c|sort -r|awk '{print $1,$2}'
#这里要求输出格式前没有空格,但是uniq输出是有空格的,使用awk重新输出7.打印只有一个数字的行
假设nowcoder.txt内容如下:
haha
1
2ab
cd
77
cat nowcoder.txt|awk 'BEGIN{
FS=""
}{
max=0
for(i=1;i<=NF;i++){
if($i ~ /[0-9]/){
max++
}
}
if(max==1){
print $0
}
}'8.文件nowcoder.txt,里面的每一行都是一个数字串,编写一个shell脚本对文件中每一行的数字串进行格式化:每3个数字加入一个逗号(,)。
例如:数字串为“123456789”,那么需要格式化为123,456,789。
cat nowcoder.txt|awk 'BEGIN{
FS=""
}{
for(i=1;i<NF;i++){
printf $i
if(i%3==NF%3){
printf ","
}
}
print $NF
}'这里有个比较困难的就是逗号每隔3个出现的起点是数字末尾而不是开头,例如1,234,567,所以这里我使用i%3==NF%3进行判断