<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆-314  評論-209  文章-0  trackbacks-0

     
    awk處理文本總結 - Alex.Wang            2008-2-19 15:55

    作為技術支持工程我們最最經常的工作就是經常碰到要處理文本文件,不管是什么數據庫最后都可以導成文本,我們就可以對他進行處理了,這樣即使你不是對所有數據庫操作都很熟悉也可以對他的數據進行處理了。

    我們必須的工具有兩個一個是shell一個是awk,awk對于處理文本文件是最最適合的掌握了awk我們就可以很方便的處理文本文件再借助一些shell命令我們可以很方便得到自己想要的結果。現在從簡單的例子來總結一下我覺得會經常碰到的問題。


    --------------------------------------------------------------------------------

    awk入門篇
     awk入門,文本內容example1.txt.
       
    user1 password1 username1 unit1 10
    user2 password2 username2 unit2 20
    user3 password3 username3 unit3 30 

     

    在unix環境中我們可以使用一下命令來打印出第一列
       
    [root@mail awk]# awk '{print $1}' example1.txt

        得到的結果是如下,解釋一下"'{" 單引號大括號包含awk語句是為了和shell 命令區別,$1的意思就是文本文件的第一列,正常的awk命令跟隨-F參數指定間隔符號,如果是空格或tab鍵就可以省略了。   
    user1
    user2
    user3 

    [root@mail awk]# awk '{if($5>20) {print $1}}' example1.txt

            這行命令和上一行比較增加了“if($5>20)”,得到的結果是

    user3

    這個if語句就沒有必要更詳細的解釋了吧!就是第5列大于20的顯示出滿足條件的第一列

    [root@mail awk]# awk '{if($5>20 || $5==10) {print $1}}' example1.txt

    user1
    user3

    在來一個初級的又增加了一個“if($5>20 || $5==10)”    做邏輯判斷邏輯判斷的三個“|| && !” 或、與、非三個可以任意加到里面,這個語句的意思是如果第5列大于20或者等于10的都顯示處理,在我們的工作中可能有用戶會要求找出所有空間大于多少的或者是空間等于多少的賬戶然后再做批量修改。

    if是awk循環中的一個還有其他很多,man awk可以看到,
       Control Statements
           The control statements are as follows:

                  if (condition) statement [ else statement ]
                  while (condition) statement
                  do statement while (condition)
                  for (expr1; expr2; expr3) statement
                  for (var in array) statement
                  break
                  continue
                  delete array[index]
                  delete array
                  exit [ expression ]
                  { statements }


    學習awk可以經常使用一下man awk 可以看到所有的函數和使用方法。   

    了解每個符號的意義我們才能更好的使用awk,最開始先記住幾個命令知道他可實現的結果我們慢慢的再去理解。


    --------------------------------------------------------------------------------

    awk中級篇
    這里順便介紹一下vi的一個替換命令,現在我們要把example1.txt文本里的空格都替換為“:”冒號這里在vi里使用的命令就是:

    %s/ /:/g     

    這個命令對于使用vi的人來說是用得最多的。我們現在做了一個新的文件example2.txt。

    user1:password1:username1:unit1:10
    user2:password2:username2:unit2:20
    user3:password3:username3:unit3:30

    現在我們來做一個awk腳本,之前都是在命令行操作,實際上所有的操作在命令行上是可以都實現的,已我們最經常使用的批量添加用戶來開始!

    script1.awk

    #!/bin/awk -f   # 當文件有可執行權限的時候你可以直接執行
                    # ./script1.awk example2.txt
                    # 如果沒有以上這行可能會出現錯誤,或者
                    # awk -f script1.awk example2.txt 參數f指腳本文件

    BEGIN {         # “BEGIN{”是awk腳本開始的地方
        FS=":";     # FS 是在awk里指分割符的意思
    }

    {                                # 接下來的“{” 是內容部分
          print "add {";             # 以下都是使用了一個awk函數print
          print "uid=" $1;
          print "userPassword=" $2;
          print "domain=eyou.com" ;
          print "bookmark=1";
          print "voicemail=1";
          print "securemail=1"
          print "storage=" $5;
          print "}";
          print ".";
    }                               # “}”    內容部分結束
    END {                           # “END{” 結束部分
        print "exit";
    }

    執行結果
    [root@mail awk]# awk -f script1.awk example2.txt
    add {
    uid=user1
    userPassword=password1
    domain=eyou.com
    bookmark=1
    voicemail=1
    securemail=1
    storage=10
    }
    .              
    .
    .
    .
    .
    .
    exit

    文本操作就是更方便一些。

    下面給兩個返回效果一樣的例子
    [root@mail awk]# awk -F: '{print $1"@"$2}' example2.txt
    [root@mail awk]# awk -F: '{printf "%s@%s\n",$1,$2}' example2.txt

    user1@password1

    這里的區別是使用print 和printf的區別,printf格式更自由一些,我們可以更加自由的指定要輸出的數據,print會自動在行尾給出空格,而printf是需要給定" \n"的,如果感興趣你可以把“\n”去掉看一下結果。%s代表字符串%d 代表數字,基本上%s都可以處理了因為在文本里一切都可以看成是字符串,不像C語言等其他語言還要區分數字、字符、字符串等。

    awk還有一些很好的函數細細研究一下還是很好用的。


    這次碰到了一個問題客戶有一個用戶列表,大概有2w用戶,他有一個有趣的工作要做,就是把每個賬戶目錄放到特定的目錄下,例如13910011234這個目錄要放到139/10/這個目錄下,從這里可以看出規律是手機號碼的前三位是二級目錄名,手機的第3、4為是三級目錄名,我們有的就只有一個用戶列表,規律找到了我們現在開始想辦法處理吧。

    example3.txt

    13910011234     
    15920312343
    13922342134
    15922334422
    ......

    第一步是要找到一個方法來吧,就是要把每一個手機號分開,最初可能你就會想到這個也沒有任何間隔,我們怎么用awk分開他們呢?說實話最初我也考慮了20多分鐘,后來想起原來學習python的時候有split函數可以分就想找找awk里是不是有類似的函數,man awk 發現substr 這個函數子串,

    [root@mail awk]# awk '{print substr($1,1,3)}'  example3.txt

    [root@mail awk]# awk '{printf "%s/%s\n",substr($1,1,3),substr($1,4,2)}'  example3.txt

    [root@mail awk]# awk '{printf "mv %s %s/%s\n",$1,substr($1,1,3),substr($1,4,2)}'  example3.txt

    以上的兩步的返回自己做一下,最后我們就得到了我們想要的結果。

    mv 13910011234 139/10
    mv 15920312343 159/20
    mv 13922342134 139/22
    mv 15922334422 159/22

    把這部分輸出拷貝到一個shell腳本里,在數據當前目錄下執行就可以了!

    substr(s, i [, n])      Returns  the at most n-character substring of s
                                   starting at i.  If n is omitted, the rest of  s
                                   is used.
                                  
    substr函數解釋,s代表我們要處理的字符串,i 是我們從這個字符串的第幾個位置上開始,n 是我們從開始的位置取多少個字符。多看看man英文也會有所提高的。                              

    awk有很多有趣的函數如果感興趣可以自己去查查看,
    man awk
    String Functions  字符串函數,舉幾個覺得常用的函數
        length([s])             Returns  the  length  of  the  string s, or the
                                   length of $0 if s is not supplied.
        length 你可以得到字符串的長度,這個是比較常用的一個函數                         
        split(s, a [, r])       Splits the string s into the  array  a  on  the
                                   regular expression r, and returns the number of
                                   fields.  If r is omitted, FS is  used  instead.
                                   The   array  a  is  cleared  first.   Splitting
                                   behaves   identically   to   field   splitting,
                                   described above.    
                                  
            tolower(str)            Returns  a copy of the string str, with all the
                                   upper-case  characters  in  str  translated  to
                                   their  corresponding  lower-case  counterparts.
                                   Non-alphabetic characters are left unchanged.
                                  
            toupper(str)            Returns a copy of the string str, with all  the
                                   lower-case  characters  in  str  translated  to
                                   their  corresponding  upper-case  counterparts.
                                   Non-alphabetic characters are left unchanged.
                                                                                        Time Functions  時間函數,我們最最常用到的是時間戳轉換函數
                                                                                      
    strftime([format [, timestamp]])
                     Formats  timestamp  according to the specification in format.
                     The timestamp should be of the same form as returned by  sys-
                     time().   If timestamp is missing, the current time of day is
                     used.  If format is missing, a default format  equivalent  to
                     the output of date(1) is used.  See the specification for the
                     strftime() function in ANSI C for the format conversions that
                     are  guaranteed  to be available.  A public-domain version of
                     strftime(3) and a man page for it come  with  gawk;  if  that
                     version  was  used to build gawk, then all of the conversions
                     described in that man page are available to gawk.                                                                                  
                                                                                      
    這里舉例說明時間戳函數是如何使用的

    [root@ent root]# date +%s | awk '{print strftime("%F %T",$0)}'
    2008-02-19 15:59:19        

    我們先使用date命令做一個時間戳,然后再把他轉換為時間                                                                                             
    還有一些我們現在可能不經常用到的函數,詳細內容man awk 自己可以看一下。
     Bit Manipulations Functions   二進制函數
     Internationalization Functions  國際標準化函數
     
     USER-DEFINED FUNCTIONS      用戶也可以自己定義自己的函數,感興趣自己可以再深入研究一下。
     
     For example:

                  function  f(p, q,     a, b)   # a and b are local
                  {
                       ...
                  }

                  /abc/     { ... ; f(1, 2) ; ... }
     DYNAMICALLY LOADING NEW FUNCTIONS  動態加載新函數,這個可能就更高級一些了!


    --------------------------------------------------------------------------------

     awk高級篇
     
     不管學習任何語言,我們學到的都是工具,工具知道的越多,我們做起工作來就越方便,但是工具在你的手里并不一定能造出好的產品,編輯腳本和編程序也是一樣的重要的是算法,別人不知道怎么處理的問題你要知道如何處理。這才能證明你比別人更高,工具只要你慢慢練習都會使用。
     
        下面給大家一個我認為是比較高級的問題了,感興趣的可以自己再想想更好的解決辦法。問題是這樣的我們有一個從ldap里導出的文件,它都是一行一個字段來說明的,每個用戶的數據是已空行分割的。我們必須把對應的uid 和userPassword找出來而且是對應的。
       
        例子:example4.txt
       
    dn: uid=cailiying,domain=ccc.com.cn,o=mail.ccc.com.cn
    uid: cailiying
    userPassword:: e21kNX0zREl4VEIwODBJdXZkTnU3WFFtS3lRPT0=
    letters: 300
    quota: 100

    dn: uid=caixiaoning,domain=ccc.com.cn,o=mail.ccc.com.cn
    userPassword:: e21kNX1kejFXU0doZWprR2RNYnV5ajJJRWl3PT0=
    letters: 300
    quota: 100
    uid: chenzheng
    domain: cqc.com.cn

    dn: uid=caixiaoning,domain=ccc.com.cn,o=mail.ccc.com.cn
    userPassword:: e21kNX1kejFXU0doZWprR2RNYnV5ajJJRWl3PT0=
    letters: 300
    quota: 100

    dn: uid=caixiaoning,domain=ccc.com.cn,o=mail.ccc.com.cn
    userPassword:: e21kNX1kejFXU0doZWprR2RNYnV5ajJJRWl3PT0=
    letters: 300
    quota: 100
    uid: chenzheng
    domain: cqc.com.cn
                                                                                        處理這個文本我們需要考慮的問題是:
    1 uid  和userPassword 并不是每一個段落里都有
    2 在每一段里面uid和userPassword 先后順序是隨機的
    3 有的段落里可能只有uid 或者只有userPassword

    從文本上分析可以看出必須使用的間隔符號,一個是空行,一個是冒號。
    冒號我們awk -F:就可以了,不過空行我們不好判斷現在想到length()這個函數,在unix里空行最多只有一個\n字符,如果一行字符數小于2我們判斷為空行,好現在間隔符號問題解決,空行只能通過循環來實現對空行的判斷。                                        

    現在碰到的另外一個問題是我們的某個段里的信息是不完全的,我們就要放棄這段這兒如何來做,就是要做兩個標記變量u 和 p  再做一個循環如果u  和  p 同事滿足我們才輸出結果下面的awk腳本就是通過這個思考來解決ldif文本的處理的!

    # 此腳本的目的是方便我們以后導ldap的其他郵件的數據,
    # 我們之前使用slapdcat -l 導出所有信息,然后我們需要
    # 整理出uid  password , 這里的設置都是默認以":" 間隔的
    # 例slapcat -l user.ldif  如果想得到一份uid 和userPassword 對應的文件,
    # 修改username = "dn"; password = "userpassword"; awk -f ldap2txt.awk user.ldif | grep uid | more  可以查看結果 (有可能是多域的郵件)
    # 如果想得到domain 所對應的密碼,修改username = "dn"; password = "userpassword";  運行 awk -f ldap2txt.awk user.ldif |grep domain | more


    #!/bin/awk -f
    # File name: ldap2txt.awk

    BEGIN {
            FS = ":";
            username = "uid";
            password = "userPassword";
    }

    {

            if(length($0) == 0 )
            {
                    if (name != "u"  &&  pword != "p")
                    {
                            printf ("%s:%s\n", name,pword);
                            name = "u";
                            pword = "p";
                    }
            }

            else 
            {
                    if ($1 == username)
                    {
                    name = "u";
                    name = $0;
                    }
                    else if($1 == password)
                    {
                    pword = "p";
                    pword = $0;
                    }
            }
    }
    END {

    }

    實際上對于學習語言首先是熟悉一些常用的函數,然后就是試著去解決別人解決過的問題,然后自己再思考一下是不是有更好,速度更快的解決辦法,實際上大部分的程序員都是在重復的使用著別人好的解決辦法,把別人的方法轉變為自己的方法,就是反復練習解決不同的問題,思考更好的方法!


    本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/blackbillow/archive/2009/01/21/3847425.aspx

    posted on 2009-08-21 14:09 xzc 閱讀(379) 評論(0)  編輯  收藏 所屬分類: linux/unix
    主站蜘蛛池模板: 午夜爱爱免费视频| 国产精品亚洲综合| 曰批全过程免费视频在线观看无码| 国产又粗又长又硬免费视频| 日韩精品免费一级视频| 伊人久久大香线蕉免费视频| 一区二区三区福利视频免费观看| 特级毛片免费播放| 午夜在线免费视频| 国产免费区在线观看十分钟| 一区在线免费观看| 国产精品视频全国免费观看| 中文字幕无线码中文字幕免费| 国产精品综合专区中文字幕免费播放 | 亚洲午夜未满十八勿入| 亚洲人成无码网站| 高清永久免费观看| 亚洲VA中文字幕无码毛片| 久久免费视频精品| 色老板亚洲视频免在线观| 日本19禁啪啪无遮挡免费动图| 亚洲欧洲精品成人久久曰| 亚洲最大av无码网址| 性色午夜视频免费男人的天堂| 亚洲天天做日日做天天欢毛片| 久久久久久免费视频| 亚洲第一街区偷拍街拍| 亚洲综合色区在线观看| 最近中文字幕mv免费高清在线| 亚洲av无码电影网| 在线日韩日本国产亚洲| 在线a免费观看最新网站| 亚洲日韩国产一区二区三区在线| 亚洲一区二区三区在线视频| 无码国产精品一区二区免费vr| 亚洲欧洲国产综合AV无码久久 | 亚洲伦乱亚洲h视频| 精品免费久久久久久久| 青青久久精品国产免费看 | 亚洲成AV人综合在线观看| 亚洲AV无码一区二区三区国产|