Tools for Extracting Text
以下為介紹在指令模式下常用到的基本指令及其應用:- File Contents: less、cat、tac、paste。
- File Excerpts: head、tail。
- Extract by Column or Field: cut。
- Extract by Keyword: grep。
File Contents (less、cat、tac、paste)
透過指令 less 來查看檔案內容,當內容大於一頁時可利用 PageUp、PageDown 來進行上下頁切換。# less /etc/issue
Red Hat Enterprise Linux Server release 5.3 (Tikanga)
Kernel \r on an \m
/etc/issue (END)
指令 cat 及 tac 則為一次列出檔案內容,cat 為從頭開始列出檔案內容 tac 為從尾開始列出檔案內容。
# 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 及 paste 若欲同時列出多個檔案內容時其排列方式不同,cat 為一個檔案內容顯示完畢後緊接另一個檔案內容而 paste 則是平行顯示 (中間隔 tab),這樣說或許很抽象但利用下列範例即可知其功能,如下檔案 f1 內容為小寫 a ~ e 而 f2 內容為大寫 A ~ E。
# 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 及 tail 則可用來快速查看檔案內容並指令顯示行數 (預設為 10 行),head 預設為顯示檔案內容前 10 行 tail 預設為顯示檔案內容後 10 行,若欲指定顯示的行數可配合參數 -n。# 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)
指令 cut 則可用來對字串進行切割的處理,如下範例為利用指令 ifconfig 顯示內容配合 grep 搜尋字串內容後後利用 cut 對標準輸出 Standard Output (1) 字串進行處理,以下為操作範例及常用參數說明。- -d: 指定切割符號。
- -f: 指定以切割符號為準取第幾個欄位。
如下操作練習利用 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)
指令 grep 可對檔案內容或標準輸出進行字串過濾的處理,以下為操作範例及常用參數說明:- -i: 忽略大小寫。
- -n: 顯示行數。
- -v: 排除指定的搜尋文字。
- -A: 找到指定條件並列出後指定行數。
- -B: 找到指定條件並列出前指定行數。
- -C: 找到指定條件並列出前/後指定行數。
- -r: 搜尋資料夾時連子目錄都一併尋找 (Recursively)。
- --color=auto: 找到指定條件時使用顏色顯示。
# 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。
- Sorting Text: sort。
- Eliminating Duplicate Lines: sort -u and uniq -c。
- Comparing Files: diff。
- Spell Check: aspell。
Text Stats (wc)
指令 wc 計算檔案的列數 (Line)、字數 (Word)、位元組 (Bytes),以下為操作範例及常用參數說明:- -l: 統計列數。
- -w: 統計字數。
- -c: 統計位元組。
# 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)
指令 sort 可對檔案內容進行排序並將結果顯示於標準輸出 (STDOUT),但請注意其指令功能並不會改變檔案內容而是僅僅顯示而以,以下為操作範例及常用參數說明:- -u: 顯示唯一 (排除重覆字)。
- -r: 反向排序。
# 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)
指令 diff 可對指定的檔案內容進行內容比對並將不同的地方顯示出來,以下為操作範例及常用參數說明:- -u: 使用統一輸出格式。
# 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 (萬用字元)
- .: any single char。
- [abc]: char in set。
- [a-c]: char in range。
- [^abc]: not in set。
- [^a-c]: not in range。
Modifies
- *: zero or more previous-char (有或沒有都可以)。
- \+: one or more previous-char (至少 1 個)。
- \?: zero or one previous-char。
- \{i \}: i 個 previous-char。
- \{i,\}: 比 i 多 previous-char。
Anchors (定錨點)
- ^: line begin with。
- $: line end with。
- \<: word begin with。
- \>: word end with。
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 來對檔案進行查看檔案內容即可知為 Windows 格式或 Unix-Like 格式,如下檔案 f1 為 Unix-Like 格式而 f2 為 Windows 格式可發現其換行字元的不同。
# 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$