shell脚本学习:不得不细心之sed和grep,sort和uniq,从细节看“认真”

         今天下午忙了一个下午写一个小脚本,中间出了很多错误,发现有关sort和uniq的细节问题,而且发现了自己写脚本一些小的方面的疏忽,编程是一门讲究严禁的学问,必须一字不差,否则轻则结果错误,重则无法运行。现在把自己的这些毛病总结下!

今天下午的脚本:

写一个脚本:
1、下载文件ftp://192.168.0.254/pub/Files/access_log至/tmp目录;
2、分析并显示/tmp/access_log文件中位于行首的IP中出现次数最多的前5个,并说明每一个出现了多少次;
3、取出/tmp/access_log文件中以http://开头,后面紧跟着一个域名或IP地址的字符串,比如:http://www.linux.com/install/images/style.css 这个串的http://www.linux.com的部分;而后显示出现次数最多的前5个;
要求:第2、3功能各以函数的方式实现;

#aceess_log的文件信息部分如下:

pleWebKit/534.13 (KHTML, like Gecko) Chrome/9.0.597.107 Safari/534.13"
192.168.0.191 - - [24/Jul/2011:17:43:17 +0800] "GET /static/image/cr180_dzx//scrolltop.gif HTTP/1.1" 304 - "http://www.linux.com/forum.php" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.13 (KHTML, like Gecko) Chrome/9.0.597.107 Safari/534.13"
192.168.0.191 - - [24/Jul/2011:17:43:17 +0800] "GET /uc_server/images/noavatar_small.gif HTTP/1.1" 304 - "http://www.linux.com/forum.php" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.13 (KHTML, like Gecko) Chrome/9.0.597.107 Safari/534.13"
192.168.0.191 - - [24/Jul/2011:17:43:17 +0800] "GET /favicon.ico HTTP/1.1" 304 - "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.13 (KHTML, like Gecko) Chrome/9.0.597.107 Safari/534.13"
192.168.0.191 - - [24/Jul/2011:17:43:17 +0800] "GET /forum.php HTTP/1.1" 200 17354 "http://www.linux.com/group.php" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.13 (KHTML, like Gecko) Chrome/9.0.597.107 Safari/534.13"
192.168.0.191 - - [24/Jul/2011:17:43:17 +0800] "GET /data/cache/style_2_common.css?o4R HTTP/1.1" 304 - "http://www.linux.com/forum.php" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.13 (KHTML, like Gecko) Chrome/9.0.597.107 Safari/534.13"
192.168.0.191 - - [24/Jul/2011:17:43:17 +0800] "GET /data/cache/style_2_forum_index.css?o4R HTTP/1.1" 304 - "http://www.linux.com/forum.php" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.13 (KHTML, like Gecko) Chrome/9.0.597.107 Safari/534.13"
192.168.0.191 - - [24/Jul/2011:17:43:17 +0800] "GET /static/js/common.js?o4R HTTP/1.1" 304 - "http://www.linux.com/forum.php" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.13 (KHTML, like Gecko) Chrome/9.0.597.107 Safari/534.13"
192.168.0.191 - - [24/Jul/2011:17:43:17 +0800] "GET /static/image/cr180_dzx//bg.jpg HTTP/1.1" 304 - "http://www.linux.com/forum.php" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.13 (KHTML, like Gecko) Chrome/9.0.597.107 Safari/534.13"
192.168.0.191 - - [24/Jul/2011:17:43:17 +0800] "GET /static/image/diy/panel-toggle.png HTTP/1.1" 304 - "http://www.linux.com/forum.php" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.13 (KHTML, like Gecko) Chrome/9.0.597.107 Safari/534.13"

 

我们的目的是要抓取指定的信息并且排名,这样肯定要用到正则表达式,而且是三个比较长的正则表达式,对正则表达式的书写有一定的要求,我在书写这三个正则表达式时,遇到了很多问题,根据题目的要求要用到sed命令把指定的内容抓出来并替换掉,而我出现了如下错误

1正则表达式最后忘了加 .*  这样对这么长的行起不到替换的作用

2在sed命令抓取后,有一些不符合要求的项也显示出来,这使用可以使用grep “http://”  去掉这些没用的行(我在这一步耽误了很长时间)

3\{  \}  写成了\{  }\     属于笔误,但书写较长的正则表达式是,这样的错误不可原谅,所以一定要实现把这些需要转移的括号给完成,然后在写要匹配的内容,以免错误的发生。

4 sed 命令忘了写 ‘’中的一个,应该实现就写好‘’避免遗忘以出错

我的第二个函数如下

function URL {
   sed '1,$s@.*\(http://[a-zA-Z]\{1,\}\.[a-zA-Z]\{1,\}\.[a-zA-Z]\{1,\}\).*@\1@g' /tmp/access_log | grep "^http://" > /tmp/tt.1
   sed '1,$s@.*\(http://[0-9]\{1,\}\.[0-9]\{1,\}\.[0-9]\{1,\}\.[0-9]\{1,\}\).*@\1@g' /tmp/access_log | grep "^http://" >> /tmp/tt.1
   echo -e "  \033[33mTIMES   Doman\033[0m  \033[5;32m<---------Here is the doman rank\033[0m"
   sort /tmp/tt.1 | uniq -c | sort -rn | head -5
}

很明显,这样长的正则表达式很容易出错,希望以后在书写sed 命令和正则表达式以及其他的命令时能吸取教训。

sort和uniq

这两个命令有一些特别容易忽视的问题,比如uniq命令 当使用sourt -n时,它并不是以数字大小比较,而是以首字符大小比较!(千万注意)所以,应该使用sort -rn来用数字排序。 而uniq 在处理特别的数据时,如果不用sort事先处理的话,会出现不是自己想要的结果,如下:

[root@dean 725-27]# sed '1,$s@.*\(http://[a-zA-Z]\{1,\}\.[a-zA-Z]\{1,\}\.[a-zA-Z]\{1,\}\).*@\1@g' /tmp/access_log | grep "^http://" | uniq -c
      2 http://www.baidu.com                    //baidu在下面又出现了!
  11983 http://www.linux.com
      1 http://i.ifeng.com
   3761 http://www.linux.com
      4 http://www.baidu.com                    //重复出现! 

这是因为uniq的处理机制,并不是合并全部重复的,而是连续重复的!所以正确的使用方法应该是,先将要处理的文件用sort先排序,将他们重复的排序在一起,然后用uniq处理

sort   file | uniq -c  | sort -rn

实现排序

 

整个脚本的代码如下:

#!/bin/bash
cd /tmp
wget ftp://192.168.0.254/pub/Files/access_log
echo -e "\033[32mdownload secessfull!\033[0m "
echo "---------------------------------------"
FILE=/tmp/access_log
function IP {
   echo -e "  \033[33mTIMES   IP\033[0m  \033[5;32m<------------ Here is the ip rank\033[0m"       
   awk '{print $1}' $FILE | sort | uniq -c | sort -rn | head -5
}
function URL {
   sed '1,$s@.*\(http://[a-zA-Z]\{1,\}\.[a-zA-Z]\{1,\}\.[a-zA-Z]\{1,\}\).*@\1@g' /tmp/access_log | grep "^http://" > /tmp/tt.1
   sed '1,$s@.*\(http://[0-9]\{1,\}\.[0-9]\{1,\}\.[0-9]\{1,\}\.[0-9]\{1,\}\).*@\1@g' /tmp/access_log | grep "^http://" >> /tmp/tt.1
   echo -e "  \033[33mTIMES   Doman\033[0m  \033[5;32m<---------Here is the doman rank\033[0m"
   sort /tmp/tt.1 | uniq -c | sort -rn | head -5
}
IP
URL
rm -f /tmp/tt.1


##总结:在书写shell脚本的时候,一定要先思考命令的用法,在明确命令的书写格式和用法时先写那些容易出错的地方,避免书写错误。其他的需要注意的方面,比如,if语句最后的fi,    if  右面紧跟的then ,  循环体后的done  ,最后删除缓存文件,case语句没条结束时的;; 最后的*)而不是‘*’) ,还有最后的esac等等

 

 

 

 

 

 

 

 

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值