站長新書 站長開講 首頁 最新文章 站長著作及審校 FreeBSD 筆記 Linux 筆記 Windows 筆記 虛擬化筆記 網管人雜誌 遊山玩水 關於本站
站長新書 VMware vSphere ICM 團購開跑了!!

Unit8-Text Processing Tools

Tools for Extracting Text

以下為介紹在指令模式下常用到的基本指令及其應用

File Contents (less、cat、tac、paste)

 #less /etc/issue
 Red Hat Enterprise Linux Server release 5.3 (Tikanga)
 Kernel \r on an \m
 /etc/issue (END)
 #cat /etc/issue                                          //從頭開始列出檔案內容
 Red Hat Enterprise Linux Server release 5.3 (Tikanga)
 Kernel \r on an \m
 #tac /etc/issue                                          //從尾開始列出檔案內容
 Kernel \r on an \m
 Red Hat Enterprise Linux Server release 5.3 (Tikanga)
 #cat f1 f2                                               //一個檔案內容顯示完畢後緊接另一個檔案內容
 a
 b
 c
 d
 e
 A
 B
 C
 D
 E
 #paste f1 f2                                             //平行顯示 (中間隔 tab)
 a       A
 b       B
 c       C
 d       D
 e       E

File Excerpts (head、tail)

 #head -n 5 /etc/passwd                                   //顯示檔案內容前 5 行
 root:x:0:0:root:/root:/bin/bash
 bin:x:1:1:bin:/bin:/sbin/nologin
 daemon:x:2:2:daemon:/sbin:/sbin/nologin
 adm:x:3:4:adm:/var/adm:/sbin/nologin
 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
 # tail -n 1 /etc/{passwd,group,shadow}                   //指定顯示多個檔案內容後 1 行
 ==> /etc/passwd <==
 weithenn:x:501:503::/home/chris:/bin/bash
 ==> /etc/group <==
 project:x:504:weithenn,chris
 ==> /etc/shadow <==
 weithenn:$1$lhpgdPzX$odVtbw1WfYDNu9L9jxi.u.:14469:0:99999:7:::

Extract by Column or Field (cut)

如下操作練習利用 grep 搜尋網卡 IP Address 配合使用 cut 指令來取出 IP Address

 #ifconfig |grep Bc                                      //指令執行結果
 inet addr: 192.168.1.10  Bcast:10.10.25.255  Mask:255.255.255.0
 #ifconfig | grep Bc | cut -f2 -d:                       //上述輸出字串結果,指定切割符號為 : 後取第二個欄位,結果如下
 192.168.1.10  Bcast
 #ifconfig |grep Bc | cut -d: -f2 | cut -d" " -f1        //上述輸出字串結果,指定切割符號為空格後取第一個欄位,結果如下
 192.168.1.10

如下操作練習利用 cut 指令取出每行的 Mail Address

 #cat mail                                               //列出檔案 mail 內容
 amy,amy@example.com
 chris,chris@example.com
 weithenn,weithenn@example.com
 #cut -d, -f2 mail                                       //指定分隔符號為逗點 (,) 後取第 2 欄位值
 amy@example.com
 chris@example.com
 weithenn@example.com

cut 指令若未指定切割符號則將使用預設的 tab,如下操作中可看到檔案 space 及 tab 內容一樣不同的地方為字元間採用空格及 tab,那如何判斷檔案中分隔階空格或 tab 呢? 可使用 cat -A 即可得知。

 #cat space                                              //列出檔案 space 內容
 a       1       tp      it
 c       2       ks      sales
 z       3       tc      account
 #cat tab                                                //列出檔案 tab 內容
 a       1       tp      it
 c       2       ks      sales
 z       3       tc      account
 #cat -A space                                           //列出檔案 space 內容 (-A 顯示所有內容,包含換行符號 $)
 a       1       tp      it$
 c       2       ks      sales$
 z       3       tc      account$
 #cat -A tab                                             //列出檔案 space 內容 (-A 顯示所有內容,包含 tab ^I,包含換行符號)、換行符號 $)
 a^I1^Itp^Iit$
 c^I2^Iks^Isales$
 z^I3^Itc^Iaccount$
 #cut -f2 space                                          //分隔符號 (預設) 為 tab 後取第 2 欄位值
 a       1       tp      it                              //因為是空格而不是 tab 所以無法擊中要找的條件
 c       2       ks      sales
 z       3       tc      account
 #cut -f2 tab                                            //分隔符號 (預設) 為 tab 後取第 2 欄位值
 1
 2
 3
 #cut -d" " -f1 space                                    //指定分隔符號為空格後取第 1 欄位值
 a 
 c
 z
 #cut -f1 tab                                            //分隔符號 (預設) 為 tab 後取第 1 欄位值
 a
 c
 z

Extract by Keyword (grep)

 #cat test                                               //查看檔案 test 內容
 ABC
 abc
 XYZ
 xyz
 #grep a test                                            //搜尋檔案內容中含 a 字元的字串
 abc
 #grep -i a test                                         //搜尋檔案內容中含 a、A 字元的字串 (忽略大小寫)
 ABC
 abc
 #grep -n a test                                         //搜尋檔案內容中含 a 字元的字串並印出行數
 2:abc
 #grep -v a test                                         //排除搜尋檔案內容中含 a 字元的字串
 ABC
 XYZ
 xyz
 #grep -A2 a test                                        //搜尋檔案內容中含 a 字元的字串並印出後 2 行
 abc
 XYZ
 xyz
 #grep -B1 a test                                        //搜尋檔案內容中含 a 字元的字串並印出前 1 行
 ABC
 abc
 #grep -C1 a test                                        //搜尋檔案內容中含 a 字元的字串並印出前後各 1 行
 ABC
 abc
 XYZ

下列操作為切換至系統放置文字目錄 /usr/share/doc 使用參數 -n 來列出行數,-r 連子目錄都尋找,--color=auto 顏色顯示擊中條件,搜尋條件為 127.0.0.1

 #cd /usr/share/doc
 #grep -nr --color=auto '127.0.0.1' *
 apr-1.2.7/CHANGES:1030:  *) Don't require that the DNS can map 127.0.0.1 when checking for
 apr-1.2.7/CHANGES:1959:     the appropriate address family for 127.0.0.1, it fails.
 cups-1.3.7/help/security.html:61:       loopback interface (127.0.0.1 or ::1) or domain
 cups-1.3.7/help/spec-ipp.html:1977:resolution is enabled.  The localhost address (127.0.0.1) is
 cups-1.3.7/help/man-cups-polld.html:23:interface (127.0.0.1) on the specified browse port for reception
 ...略...

Tools for Analyzing Text

以下為介紹在指令模式下常用到的基本指令及其應用

Text Stats (wc)

 #paste f1 f2                                             //顯示 f1 及 f2 內容
 abc     123
 def     456
 ghi     789
 jkl     111
 mno     213
 #wc -l f1                                                //統計 f1 檔案內容列數
  5 f1
 #wc -l f2                                                //統計 f2 檔案內容列數
  5 f2
 #wc -l f1 f2                                             //統計 f1 及 f2 檔案內容列數
  5 f1
  5 f2
 10 total                                                 //統計多個檔案時會有加總值

Sorting Text (sort)

 #cat f1                                                  //查看 f1 檔案內容
 X
 y
 g
 A
 e
 X
 #sort f1                                                 //排序 f1 內容 (僅顯示於 STDOUT 並未改變檔案內容本身)
 A
 e
 g
 X
 X
 y
 #sort -r f1                                              //反向排序 f1 內容 (僅顯示於 STDOUT 並未改變檔案內容本身)
 y
 X
 X
 g
 e
 A
 #sort -u f1                                              //排序後去掉重覆字 (僅顯示於 STDOUT 並未改變檔案內容本身)
 A
 e 
 g
 X
 y
 #sort -t : -k 3 -n /etc/passwd                           //對 UID 進行排序後顯示 (-t: 指定分隔符號,-k 3 取第三欄,-n 為將文字轉成數字才能正確排序)
 ...略...
 weithenn:x:500:502::/home/weithenn:/bin/bash
 chris:x:501:503::/home/chris:/bin/bash
 nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin

雖然 sort 有參數 -u 可來顯示唯一字元,但有時我們會想知道到底重覆了幾次,此時就可使用指令 uniq 配合參數 -c 來達成。

 #cut -d: -f7 /etc/passwd  | sort | uniq                  //取使用者帳號檔案第 7 個欄位排序後取唯一字元
 /bin/bash
 /bin/sync
 /sbin/halt
 /sbin/nologin
 /sbin/shutdown
 #cut -d: -f7 /etc/passwd  | sort | uniq -c               //加上 -c 參數來統計重覆了幾次
      3 /bin/bash
      1 /bin/sync
      1 /sbin/halt
     32 /sbin/nologin
      1 /sbin/shutdown

Comparing Files (diff)

 #cp -a /etc/issue /etc/issue.orig                         //複製檔案
 #vi /etc/issue                                            //修改內容將 \m 刪除
 #head /etc/issue /etc/issue.orig                          //顯示檔案內容前 10 行
 ==> /etc/issue <==
 Red Hat Enterprise Linux Server release 5.3 (Tikanga)
 Kernel \r on an
 ==> /etc/issue.orig <==
 Red Hat Enterprise Linux Server release 5.3 (Tikanga)
 Kernel \r on an \m
 #diff /etc/issue /etc/issue.orig                          //使用 diff 對 2 個檔案進行比對
 2c2
 < Kernel \r on an
 ---
 > Kernel \r on an \m
 #diff -u /etc/issue /etc/issue.orig                       //-u 參數使人更容易判斷檔案內容哪裡不同
 --- /etc/issue  2009-08-29 09:54:22.000000000 +0800
 +++ /etc/issue.orig     2008-12-16 06:36:00.000000000 +0800
 @@ -1,3 +1,3 @@
  Red Hat Enterprise Linux Server release 5.3 (Tikanga)
 -Kernel \r on an
 +Kernel \r on an \m

Spell Check (aspell)

指令 aspell 可對指定的檔案內容進行拼字比對,以下為操作範例

 #cat f1
 apple
 emil address 
 #aspell check f1                                         //出現如下選單讓您選擇正確的字
 1) Emil                                                                  6) Mil
 2) Emile                                                                 7) mil
 3) Emili                                                                 8) Amil
 4) Emily                                                                 9) emir
 5) email                                                                 0) emit
 i) Ignore                                                                I) Ignore all
 r) Replace                                                               R) Replace all
 a) Add                                                                   l) Add Lower
 b) Abort                                                                 x) Exit

Tools for Manipulating Text (sed)

sed 指令可快速搜尋檔案內容某個關鍵字並進行取代的動作,但請注意其指令功能並不會改變檔案內容而是僅僅顯示而以,以下為操作範例

 #cat f1
 1,cat,dog,cat,dog
 2,dog,cat,dog,Cat
 3,cat,dog,cat,dog
 4,dog,cat,dog,Cat
 #sed 's/cat/dog/' f1                                     //將第 1 個關鍵字 cat 取代為 dog (並未改變檔案內容)
 1,dog,dog,cat,dog
 2,dog,dog,dog,Cat
 3,dog,dog,cat,dog
 4,dog,dog,dog,Cat
 #sed 's/cat/dog/g' f1                                    //將所有關鍵字 cat 取代為 dog (並未改變檔案內容)
 1,dog,dog,dog,dog
 2,dog,dog,dog,Cat
 3,dog,dog,dog,dog
 4,dog,dog,dog,Cat
 #sed 's/[Cc]at/dog/g' f1                                 //將所有關鍵字 Cat, cat 取代為 dog (並未改變檔案內容)
 1,dog,dog,dog,dog
 2,dog,dog,dog,dog
 3,dog,dog,dog,dog
 4,dog,dog,dog,dog
 #sed '1,2s/[Cc]at/dog/g' f1                              //將所有關鍵字 Cat, cat 取代為 dog 範圍為 1 ~ 2 列(並未改變檔案內容)
 1,dog,dog,dog,dog
 2,dog,dog,dog,dog
 3,dog,dog,dog,dog
 4,dog,dog,dog,Cat

Regular Expression

常用來配合 Regular Expression 的指令有 grep、swk、sed、vi、less,不過下列提到的 Regular Expression 字元與之前章節 6 提到的 Command Line Shortcuts File Globbing 字元不同,且建議使用 Regular Expression 時前後使用單或雙引號括住。 例如使用者帳號中有 john 及 johnson 若我們想使用 grep 來尋找 john 使者用帳號則會連 johnson 使用者帳號也一併列出,此時我們便可利用 Anchors (定錨點) 來配合處理。

 #grep john /etc/passwd
 john:x:502:505::/home/john:/bin/bash
 johnson:x:503:506::/home/johnson:/bin/bash

我們透過 Anchors (定錨點) 來指定搜尋 /etc/passwd 內容時僅搜尋開頭為 john: 內容。

 #grep '^john:' /etc/passwd
 john:x:502:505::/home/john:/bin/bash

知道了 Regular Expression 好用之處後開始介紹常用的過濾字元

Wildcard Characters (萬用字元) 練習

檔案 people 中有五個人名分別為 alex、alen、anne、bill、billy 利用上述的 Wildcard Characters (萬用字元) 來對其搜尋內容進行過濾。

 #cat people
 alex
 alen
 anne
 bill
 billy
 #grep bill people                                        //搜尋開頭為 bill 相關名字
 bill
 billy
 #grep bill. people                                       //搜尋開頭為 bill 後接任一字元 (any single char)
 billy
 #grep ale[a-o] people                                    //搜尋開頭為 ale 後面字元為 a ~ o 之間的字元 (char in range)
 alen
 #grep ale[^a-o] people                                   //搜尋開頭為 ale 後面字元排除 a ~ o 之間的字元 (not in range)
 alex
 #grep ale[nx] people                                     //搜尋開頭為 ale 後面字元為 n、x 的字元 (char in set)
 alex
 alen
 #grep ale[anbxc] people                                  //搜尋開頭為 ale 後面字元為 a、n、b、x、c 的字元 (char in set)
 alex
 alen

Modifies 練習

檔案 ab 中分別有不同字串長度的 a、b,利用 Modifies 來對其搜尋內容進行過濾。

 #cat ab
 a
 aa
 aaa
 aaaa
 aaaaa
 b
 bb
 bbb
 bbbb
 bbbbb
 bab
 bbaa
 baab
 bbbaaa
 #grep "a*" ab                                              //搜尋開頭為 a 後面字元為 0 個 a 或以上的其它字元 (zero or more previous-char)
 a
 aa
 aaa
 aaaa
 aaaaa
 b
 bb
 bbb
 bbbb
 bbbbb
 bab
 bbaa
 baab
 bbbaaa
 #grep a\+ ab                                              //未使用引號括住 Regular Expression
 #grep "a\+" ab                                            //搜尋開頭為 a 後面字元為 1 個 a 或以上的字元 (one or more previous-char)
 a
 aa
 aaa
 aaaa
 aaaaa
 bab
 bbaa
 baab
 bbbaaa
 #grep "a\?" ab                                           //搜尋開頭為 a 後面字元為 0 個 a 或 1 個以上的其它字元 (zero or one previous-char)
 a 
 aa
 aaa
 aaaa
 aaaaa
 b
 bb
 bbb
 bbbb
 bbbbb
 bab
 bbaa
 baab
 bbbaaa
 #grep "a\{3\}" ab                                       //搜尋開頭為 3 個(含) a 字元的字串 (i 個 previous-char)
 aaa
 aaaa
 aaaaa
 bbbaaa
 #grep "a\{4,\}" ab                                      //搜尋開頭為 4 個(含) a 字元的字串 (比 i 多 previous-char)
 aaaa
 aaaaa

Anchors (定錨點) 練習

檔案 bad 中分別有不同字串長度的文字,利用 Anchors (定錨點) 來對其搜尋內容進行過濾。

 #cat bad                                                //檔案 bad 內容
 bad
 bad boy
 so bad
 #grep "^bad" bad                                        //搜尋檔案中每行開頭為 bad 的字串 (line begin with)
 bad
 bad boy
 #grep "bad$" bad                                        //搜尋檔案中每行結尾為 bad 的字串 (line end with)
 bad
 so bad
 #grep "^bad$" bad                                       //搜尋檔案中每行開頭及結尾為 bad 的字串
 bad
 #grep "\<so" bad                                        //搜尋檔案中含有 so 開頭的字串 (word begin with)
 so bad
 #grep "\>so" bad                                        //搜尋檔案中含有 so 結尾的字串 (word end with)

最後來個 Regular Expression 綜合練習,查詢檔案內容中取出您要的條件字串

 #cat test                                               //列出檔案 test 內容
 123456789012345678901234567890
 abcdefghij12345678
 www.google.com.tw.
 aaaaabbbbbcccccdddddeeeee
 aaaaa tw.yahoo.com deeeee
 kenny
 bill
 #grep '^[a-z 0-9]\{18\}$' test                          //搜尋字串開頭為 a ~ z 及 0 ~ 9 結尾的字串且字元數為 18
 abcdefghij12345678
 #grep '^[a-z 0-9]\{25\}$' test                          //搜尋字串開頭為 a ~ z 及 0 ~ 9 結尾的字串且字元數為 25
 aaaaabbbbbcccccdddddeeeee
 #grep '^[a-z 0-9]\{5\}$' test                           //搜尋字串開頭為 a ~ z 及 0 ~ 9 結尾的字串且字元數為 5
 kenny

補充

補充1. Windows 與 Unix-Like 檔案格式轉換 (dos2unix、unix2dos)

由於 Windows 與 Unix-Like 對於內容中 換行字元 的處理方式不同,因此便會發生您在 Windows 上修改好檔案內容而上傳至 Unix-Like 環境執行時發生問題,此時便為換行符號所導致,這時便可利用簡單的指令來進行檔案格式內換行字元的轉換。

 #cat -A f1                                              //Unix-Like 格式
 a$
 b$
 c$
 d$
 e$
 #cat -A f2                                              //Windows 格式
 A^M$
 B^M$
 C^M$
 D^M$
 E^M$

我們也可透過指令 od 來查看檔案的 ASCII 碼,可發現 Unix-Like 格式其換行字元為 \n (10 New Line) 而 Windows 格式其換行字元為 \r \n (13 Carriage Return 及 10 New Line) 所組成。

 #od -t c f1
 0000000   a  \n   b  \n   c  \n   d  \n   e  \n
 0000012
 #od -t c f2
 0000000   A  \r  \n   B  \r  \n   C  \r  \n   D  \r  \n   E  \r  \n
 0000017

因此我們可以使用指令 dos2unix、unix2dos 顧名思義這二個指令即對檔案內容的換行字元進行處理。

 #cat -A f1                                              //Unix-Like 格式
 a$
 b$
 c$
 d$
 e$
 #unix2dos f1                                            //執行轉換換行字元指令 (Unix-Like -> Windows)
 unix2dos: converting file f1 to DOS format ...
 #cat -A f1                                              //Windows 格式
 a^M$
 b^M$
 c^M$
 d^M$
 e^M$
 #dos2unix f1                                            //執行轉換換行字元指令 (Windows -> Unix-Like)
 dos2unix: converting file f1 to UNIX format ...
 #cat -A f1                                              //Unix-Like 格式
 a$
 b$
 c$
 d$
 e$

Reference

[Wikipedia - Regular expression]

[洪朝貴 - 字串樣版 Regexp: 兼談長線學習投資]

[中央研究院計算中心 - Regular Expression 簡介]

Go To Oddmuse OrgGo To FreeBSD OrgCreative Commons 2.5 Taiwansitestates.com