Linux系統程式設計(19)——正規表示式在sed和awk中的使用
sed意為流編輯器(Stream Editor),在Shell指令碼和Makefile中作為過濾器使用非常普遍,也就是把前一個程式的輸出引入sed的輸入,經過一系列編輯命令轉換為另一種格式輸出。sed和vi都源於早期UNIX的ed工具,所以很多sed命令和vi的末行命令是相同的。
sed命令列的基本格式為
sed option 'script' file1 file2 ...
sed option -f scriptfile file1 file2 ...
sed處理的檔案既可以由標準輸入重定向得到,也可以當命令列引數傳入,命令列引數可以一次傳入多個檔案,sed會依次處理。sed的編輯命令可以直接當命令列引數傳入,也可以寫成一個指令碼檔案然後用-f引數指定,編輯命令的格式為
/pattern/action其中pattern是正規表示式,action是編輯操作。sed程式一行一行讀出待處理檔案,如果某一行與pattern匹配,則執行相應的action,如果一條命令沒有pattern而只有action,這個action將作用於待處理檔案的每一行。
常用的sed命令:
/pattern/p 列印匹配pattern的行
/pattern/d 刪除匹配pattern的行
/pattern/s/pattern1/pattern2/ 查詢符合pattern的行,將該行第一個匹配pattern1的字串替換為pattern2
/pattern/s/pattern1/pattern2/g 查詢符合pattern的行,將該行所有匹配pattern1的字串替換為pattern2
使用p命令需要注意,sed是把待處理檔案的內容連同處理結果一起輸出到標準輸出的,因此p命令表示除了把檔案內容列印出來之外還額外列印一遍匹配pattern的行。比如一個檔案testfile的內容是
123
abc
456
列印其中包含abc的行
$ sed '/abc/p' testfile
123
abc
abc
456
要想只輸出處理結果,應加上-n選項,這種用法相當於grep命令
$ sed -n '/abc/p' testfile
abc
使用d命令就不需要-n引數了,比如刪除含有abc的行
$ sed '/abc/d' testfile
123
456
注意,sed命令不會修改原檔案,刪除命令只表示某些行不列印輸出,而不是從原檔案中刪去。
使用查詢替換命令時,可以把匹配pattern1的字串複製到pattern2中,比如:
$ sed 's/bc/-&-/' testfile
123
a-bc-
456
pattern2中的&表示原檔案的當前行中與pattern1相匹配的字串,再比如:
$ sed 's/\([0-9]\)\([0-9]\)/-\1-~\2~/'testfile
-1-~2~3
abc
-4-~5~6
pattern2中的\1表示與pattern1的第一個()括號相匹配的內容,\2表示與pattern1的第二個()括號相匹配的內容。sed預設使用Basic正規表示式規範,如果指定了-r選項則使用Extended規範,那麼()括號就不必轉義了。
如果testfile的內容是
<html><head><title>HelloWorld</title>
<body>Welcome to the world ofregexp!</body></html>
現在要去掉所有的HTML標籤,使輸出結果為
Hello World
Welcome to the world of regexp!
怎麼做呢?如果用下面的命令
$ sed 's/<.*>//g' testfile
結果是兩個空行,把所有字元都過濾掉了。這是因為,正規表示式中的數量限定符會匹配儘可能長的字串,這稱為貪心。
sed以行為單位處理檔案,awk比sed強的地方在於不僅能以行為單位還能以列為單位處理檔案。awk預設的行分隔符是換行,預設的列分隔符是連續的空格和Tab,但是行分隔符和列分隔符都可以自定義,比如/etc/passwd檔案的每一行有若干個欄位,欄位之間以:分隔,就可以重新定義awk的列分隔符為:並以列為單位處理這個檔案。awk實際上是一門很複雜的指令碼語言,還有像C語言一樣的分支和迴圈結構,但是基本用法和sed類似,awk命令列的基本形式為:
awk option 'script' file1 file2 ...
awk option -f scriptfile file1 file2 ...
和sed一樣,awk處理的檔案既可以由標準輸入重定向得到,也可以當命令列引數傳入,編輯命令可以直接當命令列引數傳入,也可以用-f引數指定一個指令碼檔案,編輯命令的格式為:
/pattern/{actions}
condition{actions}
和sed類似,pattern是正規表示式,actions是一系列操作。awk程式一行一行讀出待處理檔案,如果某一行與pattern匹配,或者滿足condition條件,則執行相應的actions,如果一條awk命令只有actions部分,則actions作用於待處理檔案的每一行。比如檔案testfile的內容表示某商店的庫存量:
ProductA 30
ProductB 76
ProductC 55
列印每一行的第二列:
$ awk '{print $2;}' testfile
30
76
55
自動變數$1、$2分別表示第一列、第二列等,類似於Shell指令碼的位置引數,而$0表示整個當前行。再比如,如果某種產品的庫存量低於75則在行末標註需要訂貨:
$ awk '$2<75 {printf"%s\t%s\n", $0, "REORDER";} $2>=75 {print $0;}' testfile
ProductA 30 REORDER
ProductB 76
ProductC 55 REORDER
可見awk也有和C語言非常相似的printf函式。awk命令的condition部分還可以是兩個特殊的condition-BEGIN和END,對於每個待處理檔案,BEGIN後面的actions在處理整個檔案之前執行一次,END後面的actions在整個檔案處理完之後執行一次。
awk命令可以像C語言一樣使用變數(但不需要定義變數),比如統計一個檔案中的空行數
$ awk '/^ *$/ {x=x+1;} END {print x;}'testfil
e就像Shell的環境變數一樣,有些awk變數是預定義的有特殊含義的。
awk常用的內建變數:
FILENAME 當前輸入檔案的檔名,該變數是隻讀的
NR 當前行的行號,該變數是隻讀的,R代表record
NF 當前行所擁有的列數,該變數是隻讀的,F代表field
OFS 輸出格式的列分隔符,預設是空格
FS 輸入檔案的列分融符,預設是連續的空格和Tab
ORS 輸出格式的行分隔符,預設是換行符
RS 輸入檔案的行分隔符,預設是換行符
例如列印系統中的使用者帳號列表
$ awk 'BEGIN {FS=":"} {print$1;}' /etc/passwdawk
相關文章
- shell程式設計(四)| sed 正規表示式程式設計
- Linux系統程式設計(16)——正規表示式入門Linux程式設計
- Linux系統程式設計(17)——正規表示式進階Linux程式設計
- 正規表示式在Java中的使用Java
- Linux系統程式設計(18)——正規表示式實用舉例Linux程式設計
- MongoDB正規表示式在索引中的使用MongoDB索引
- 在Linux中,如何使用awk和sed進行文字處理?Linux
- UNIX和LINUX系統的SHELL正規表示式語法(轉)Linux
- Qt Creator程式設計之正規表示式QT程式設計
- shell程式設計(四)| grep正規表示式程式設計
- 05 shell程式設計之正規表示式程式設計
- Linux中基本正規表示式Linux
- Sed 命令詳解 正規表示式元字元字元
- 在UltraEdit中使用正規表示式
- Dreamweaver網頁設計中的正規表示式使用方法教程網頁
- 正規表示式在iOS中的運用iOS
- Linux之grep中的正規表示式Linux
- Linux 的正規表示式Linux
- 在JAVA中使用正規表示式 (轉)Java
- Linux grep命令和正規表示式Linux
- Linux正規表示式使用指南Linux
- 【Linux】正規表示式Linux
- [Shell] awk學習(3)-regular expression 正規表示式Express
- QTP的描述性程式設計與正規表示式QT程式設計
- java中的正規表示式Java
- JS中的正規表示式JS
- iOS中的正規表示式iOS
- Oracle中的正規表示式Oracle
- 系統認識JavaScript正規表示式JavaScript
- 在angular路由中使用正規表示式Angular路由
- 在UltraEdit中使用正規表示式(轉載)
- js中在迴圈中使用正規表示式遇到的小坑JS
- linux grep 正規表示式Linux
- PostgreSQL中的模式匹配和正規表示式 - DasSQL模式
- python中re模組的使用(正規表示式)Python
- 正規表示式在iOS開發中的應用iOS
- Linux grep 命令中的正規表示式詳解Linux
- 理解正規表示式(程式設計師第3期文章)程式設計師