shell指令碼學習:不得不細心之sed和grep,sort和uniq,從細節看“認真”

來源:互聯網
上載者:User

         今天下午忙了一個下午寫一個小指令碼,中間出了很多錯誤,發現有關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"

 

我們的目的是要抓取指定的資訊並且排名,這樣肯定要用到Regex,而且是三個比較長的Regex,對Regex的書寫有一定的要求,我在書寫這三個Regex時,遇到了很多問題,根據題目的要求要用到sed命令把指定的內容抓出來並替換掉,而我出現了如下錯誤

1Regex最後忘了加 .*  這樣對這麼長的行起不到替換的作用

2在sed命令抓取後,有一些不符合要求的項也顯示出來,這使用可以使用grep “http://”  去掉這些沒用的行(我在這一步耽誤了很長時間)

3\{  \}  寫成了\{  }\     屬於筆誤,但書寫較長的Regex是,這樣的錯誤不可原諒,所以一定要實現把這些需要轉移的括弧給完成,然後在寫要匹配的內容,以免錯誤的發生。

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
}

很明顯,這樣長的Regex很容易出錯,希望以後在書寫sed 命令和Regex以及其他的命令時能吸取教訓。

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/bashcd /tmpwget ftp://192.168.0.254/pub/Files/access_logecho -e "\033[32mdownload secessfull!\033[0m "echo "---------------------------------------"FILE=/tmp/access_logfunction 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}IPURLrm -f /tmp/tt.1

##總結:在書寫shell指令碼的時候,一定要先思考命令的用法,在明確命令的書寫格式和用法時先寫那些容易出錯的地方,避免書寫錯誤。其他的需要注意的方面,比如,if語句最後的fi,    if  右面緊跟的then ,  迴圈體後的done  ,最後刪除快取檔案,case語句沒條結束時的;; 最後的*)而不是‘*’) ,還有最後的esac等等

 

 

 

 

 

 

 

 

 

 

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.