200 likes | 404 Views
Linux 基礎學習. Chapter 12 Regular Expression VBird 2005/09/02. 內容. 什麼是正規表示法 基礎型正規表示法 延伸型正規表示法 格式化列印 (printf) sed awk 相關應用. 什麼是正規表示法. 簡單說明: 稱呼為 “正規表示式” 或 “常規表示式” 英文使用 Regular Expression 或者是 regexp 表示 用途: 正規表示法就是處理字串的方法; 以行為單位, 來進行字串的處理行為; 他透過一些特殊符號的輔助;
E N D
Linux 基礎學習 Chapter 12 Regular Expression VBird 2005/09/02 Linux基礎--regular express
內容 • 什麼是正規表示法 • 基礎型正規表示法 • 延伸型正規表示法 • 格式化列印 (printf) • sed • awk • 相關應用 Linux基礎--regular express
什麼是正規表示法 • 簡單說明: • 稱呼為 “正規表示式” 或 “常規表示式” • 英文使用 Regular Expression 或者是 regexp 表示 • 用途: • 正規表示法就是處理字串的方法; • 以行為單位, 來進行字串的處理行為; • 他透過一些特殊符號的輔助; • 可以讓使用者輕易的達到 搜尋/取代 某特定字串的處理程序! Linux基礎--regular express
什麼是正規表示法(續) • 分類 • 基本型 (General Regexp) • 延伸型 (Extended Regexp) • 記得語系資料 (LANG=en, LANG=C) • 支援程式項目 • vi、vim、gvim • sed • grep、egrep、fgrep • 垃圾信件分析、登錄檔分析、重要訊息擷取等。 • 只有支援正規表示法的軟體才能用 RE 字符表示。 Linux基礎--regular express
基礎正規表示法 • 字串擷取指令:grep [-acinv] '搜尋字串' filename • -a :將 binary 檔案以 text 檔案的方式搜尋資料 • -c :計算找到 '搜尋字串' 的次數 • -i :忽略大小寫的不同,所以大小寫視為相同 • -n :順便輸出行號 • -v :反向選擇,亦即顯示出沒有 ‘搜尋字串’ 內容的那一行! • 練習: • 在 last 輸出的資料中,擷取出有 root 的紀錄; • 搜尋 /var/log/messages 內,含有 root 的紀錄? • 搜尋 /var/log/messages 內,不含 cron 的紀錄? Linux基礎--regular express
基礎正規表示法(續) • 基本型項目 • . 表示任一單一字元(一定有一個字元,但不包含換行符號) • [] 表示清單內任一單一字元 • 使用 – 表示範圍 ex [a-z] • 使用 ^ 表示排除 ex [^A-Z] • ^ 表示為首字元 • $ 表示為尾字元 • \ 表示讓後面字元失去原特殊意義成為一般字元 • * 表示前面指定樣式可以出現 0 次至多次 • \{n,m\} 連續 n 到 m 個的『前一個 RE 字符』 Linux基礎--regular express
基礎正規表示法(續) • 範例: • 先下載:wget http://linux.vbird.org/linux_basic/0330regularex/regular_express.txt • 找出上個檔案中,有 “the” 字樣的那一行,並輸出行號; grep -n ‘the’ regular_express.txt • 呈上題,若忽略大小寫的話? grep -in ‘the’ regular_express.txt • 找出 test 或 taste 這兩個字串所在行? grep -n ‘t[ae]st’ regular_express.txt • 找出含有 oo 的那一行? grep -n ‘oo’ regular_express.txt • 呈上題,但 oo 之前不能是 g 的話? grep -n ‘[^g]oo’ regular_express.txt Linux基礎--regular express
基礎正規表示法(續) • 範例: • 呈上,若 oo 前面不能是小寫字元? grep -n ‘[^a-z]oo’ regular_express.txt • 呈上,取出有數字的該行? grep -n ‘[0-9]’ regular_express.txt • 若以 the 為開頭的那一行? grep -n ‘^the’ regular_express.txt • 若以小寫字元為開頭? grep -n ‘^[a-z]’ regular_express.txt • 開頭並不是英文字元? grep -n ‘^[^A-Za-z]’ regular_express.txt Linux基礎--regular express
基礎正規表示法(續) • 範例: • 該行結尾含有小數點? grep -n ‘\.$’ regular_express.txt • 取出空白行? grep -n ‘^$’ regular_express.txt • 請取出 /etc/man.config 內不以 # 開頭,及去除空白行? grep -v ‘^#’ /etc/man.config | grep -v ‘^$’ • 找出 g??d ,亦即共含有四位字元的那一行? grep -n ‘g..d’ regular_express.txt • 含有連續兩個以上的 o 的那一行? grep -n ‘ooo*’ regular_express.txt Linux基礎--regular express
基礎正規表示法(續) • 範例: • 含有不一定連續的兩個 g 的那一行? grep -n ‘g.*g’ regular_express.txt • 含有 2~5 個 o 的那一行? grep -n ‘o\{2,5\}’ regular_express.txt • 找出在 /bin 底下,不以 a 到 j 為開頭的檔名? ls -l /bin/[!a-j]* ls -l `find /bin -type f` | grep '/bin/[^a-j]' |more • 我想要找出 /etc/ 底下的所有檔案中,含有*的那個檔案 grep '\*' /etc/* Linux基礎--regular express
延伸正規表示法 • 延伸型項目: • + 表示前面指定樣式至少出現 1 次以上 • ? 表示前面指定樣式出現 0 次或是 1 次 • ( ) 表示集合 • A|B 表示 A 或者是 B • {n} 表示前面指定樣式只出現 n 次 • {n,} 表示前面指定樣式至少出現 n 次 • {n,m} 表示前面指定樣式至少出現 n 次,但是不超過 m 次 Linux基礎--regular express
延伸正規表示法(續) • 需要使用 egrep 或 grep -E 來執行 • 練習: • 找出 MAN 或 MAP 在 /etc/man.config 中 egrep ‘MA(N|P)’ /etc/manpath.config • 找出四位數以上在 /usr/share/doc/cpus*/*裡面的檔案 egrep ‘[0-9]{4,}’ /usr/share/doc/cups-/* • 找出至少出現兩個 M 以上的行在 /etc/man.config 當中 egrep “MM+” /etc/man.config Linux基礎--regular express
格式化列印 (printf) • printf '列印格式' 實際內容 • 關於格式方面的幾個特殊樣式: • \a 警告聲音輸出 • \b 倒退鍵(backspace) • \f 清除螢幕 (form feed) • \n 輸出新的一行 • \r 亦即 Enter 按鍵 • \t 水平的 [tab] 按鍵 • \v 垂直的 [tabl] 按鍵 • 關於 C 程式語言內,常見的變數格式 • %ns 那個 n 是數字, s 代表 string ,亦即多少個字元; • %ni 那個 n 是數字, i 代表 integer ,亦即多少整數位數 • %N.nf 那個 n 與 N 都是數字, f 代表 floating (浮點),如果有小數位數,假設我共要十個位數,但小數點有兩位,即為 %10.2f 囉! Linux基礎--regular express
格式化列印 (printf)(續) • 製作一個檔案,內容如下:(檔名 printf.txt) Name Chinese English Math Average DmTsai 80 60 92 77.33 VBird 75 55 80 70.00 Ken 60 90 70 73.33 • 將剛剛上頭的資料變成檔案,僅列出姓名與成績:(用 [tab] 分隔 printf '%s\t %s\t %s\t %s\t %s\t \n' `cat printf.txt` • 將上述資料關於第二行以後,分別以字串、整數、小數點來顯示 printf '%10s %5i %5i %5i %8.2f \n' `cat printf.txt |\ > grep -v Name` Linux基礎--regular express
sed • sed [-nefr] [動作] • -n • 使用(silent)模式。在一般 sed 的用法中,所有來自 STDIN 的資料一般都會被列出到螢幕上。但如果加上 -n 參數後,則只有經過 sed 特殊處理的那一行(或者動作)才會被列出來。 • -e • 直接在指令列模式上進行 sed 的動作編輯; • -f • 直接將 sed 的動作寫在一個檔案內, -f filename 則可以執行 filename 內的 sed 動作; • -r • sed 的動作支援的是延伸型正規表示法的語法。(預設是基礎正規表示法語法) Linux基礎--regular express
sed(續) • sed [-nefr] [n1[,n2]]function • a • 新增, a 的後面可以接字串,而這些字串會在新的一行出現(下一行) • c • 取代, c 的後面可以接字串,這些字串可以取代 n1,n2 之間的行! • d • 刪除,因為是刪除啊,所以 d 後面通常不接任何咚咚; • i • 插入, i 的後面可以接字串,而這些字串會在新的一行出現(上一行); • p • 列印,亦即將某個選擇的資料印出。通常 p 會與參數 sed -n 一起運作~ • s • 搜尋,不但可以搜尋,還能夠進行取代的工作哩!通常這個 s 的動作可以搭配正規表示法!例如 1,20s/old/new/g 就是啦! Linux基礎--regular express
sed(續) • 範例: • 將 /etc/passwd 的內容列出,需要列印行號,且將第 2~5 行刪除 nl /etc/passwd | sed '2,5d‘ • 呈上題,在第二行後(亦即是加在第三行)加上『drink tea?』 nl /etc/passwd | sed '2a drink tea‘ • 在第二行後面加入兩行字,例如『Drink tea or .....』『drink beer?』 nl /etc/passwd | sed '2a Drink tea or ......\ > drink beer ?‘ • 我想將第2-5行的內容取代成為『No 2-5 number』呢? nl /etc/passwd | sed '2,5c No 2-5 number‘ • 僅列出第 5-7 行 nl /etc/passwd | sed -n '5,7p' • 我們可以使用 ifconfig 來列出 IP ,若僅要 eth0 的 IP 時? ifconfig eth0 | grep 'inet ' | sed 's/^.*addr://g' | sed 's/Bcast.*$//g' Linux基礎--regular express
awk • 指令下達: • awk '條件類型1{動作1} 條件類型2{動作2} ...' filename • 基礎應用: • 將 last 輸出的資訊中,第 1, 3 欄位輸出? • last | awk '{print $1 "\t" $3}‘ • awk 的處理流程 • 讀入第一行,並將第一行的資料填入 $0, $1, $2.... 等變數當中; • 依據 "條件類型" 的限制,判斷是否需要進行後面的 "動作"; • 做完所有的動作與條件類型; • 若還有後續的『行』的資料,則重複上面 1~3 的步驟,直到所有的資料都讀完為止。 Linux基礎--regular express
awk(續) • awk 的內建變數 • NF 每一行 ($0) 擁有的欄位總數 • NR 目前 awk 所處理的是『第幾行』資料 • FS 目前的分隔字元,預設是空白鍵 • 簡單範例: • 列出 last 內每一行的帳號,並且列出目前處理的行數, 並且說明,該行有多少欄位 • last | awk '{print $1 "\t lines: " NR "\t columes: " NF}‘ Linux基礎--regular express
相關應用 • 新舊檔案的製作: • 將 /etc/passwd 複製到 /tmp/old 裡面去 • mkdir /tmp/old • cp -a /etc/passwd /tmp/old • 將 /etc/passwd 內容中,第 10 行加入加入一行,內容為 “testing:x:350:350” ,且將內容儲存到 /tmp/new/passwd 中。 • mkdir /tmp/new • sed '10a testing:x:350:350' /etc/passwd >> /tmp/new/passwd • diff 檔案比對: • diff /etc/passwd /tmp/test/passwd • cmp 字元比對(僅列出第一個差異點) • cmp /etc/passwd /tmp/test/passwd • pr 列印準備! (pr /etc/passwd) Linux基礎--regular express