詳解流編輯器 sed 和 程式語言 awk

s1mba發表於2014-02-19

一、流編輯器 sed

sed 是一個精簡的、非互動式的流式編輯器,它在命令列中輸入編輯命令和指定檔名,然後在螢幕上檢視輸出。
逐行讀取檔案內容儲存在臨時緩衝區中,稱為“模式空間”(pattern space),接著用sed命令處理緩衝區中的內容,處理完成後,把緩衝區的內容送往螢幕。接著處理下一行,這樣不斷重複,直到檔案末尾。原檔案內容並沒有改變。

(一)sed 簡單用法

選項

-e

連線多個編輯命令(直接在命令列模式上進行sed的操作)

-f

指定sed指令碼檔名(將sed的操作寫在一個檔案裡,用的時候 -f filename 就可以按照內容進行sed操作了)

-n

阻止輸入行自動輸出(只有經過sed處理過的行才顯示出來,其他不顯示)

-r                                 使之支援擴充套件正規表示式

                                                  -i                                  後跟檔名,sed 的操作會更改到檔案

sed ‘4,$d’ test.in  
sed ‘3q’ test.in
sed ‘s/public/PUBLIC/’ test.in
sed -n ‘s/public/PUBLIC/p’ test.in


指定多個命令的三種方法:

1、用分號分隔命令
sed 's/public/PUBLIC/;s/north/NORTH/' test.in 

2、每個命令前放置-e
sed -e 's/public/PUBLIC/' -e 's/north/NORTH/' test.in

3、使用分行命令功能,在輸入單引號後按return鍵就會出現多行提示符(>)
sed '
> s/public/PUBLIC/
> s/north/NORTH/' test.in

在指令碼中使用sed命令:

test.sed檔案內容如下:
s/public/PUBLIC/
s/north/NORTH/


sed -f test.sed test.in

(二)sed 命令語法
sed_cmd使用格式:[address]  sed_edit_cmd(通常用單引號括起來),其中addresssed行定位模式,用於指定將要被 sed編輯的行。如果省略,sed將編輯所有的行。sed_edit_cmdsed對被編輯行將要進行的編輯操作

sed_cmdaddress的定位方式:

n

表示第 n

$

表示最後一行

m,n

表示從第 m 行到第 n

/pattern/

查詢包含指定模式的行。如 /disk//[a-z]/

/pattern/,n

表示從包含指定模式的行 到 第 n

n,/pattern/

表示從第 n 行 到 包含指定模式的行

/模式1/,/模式2/

表示從包含模式1 到 包含模式2的行

反向選擇,如 m,n的結果與m,n 相反


(三)常用的sed_edit_cmd:





(四)常用sed編輯命令小結

 q:退出,讀取到指定行後退出 sed

sed  '3q' test.in


p

列印匹配行

s

替換命令

=

顯示匹配行的行號

l

顯示指定行中所有字元

d

刪除匹配的行

r

讀檔案

a\

指定行後面追加文字

w

寫檔案

i\

指定行前面追加文字

n

讀取指定行的下面一行

c\

用新文字替換指定的行

q

退出 sed



二、程式語言awk

awk 是一種用於處理資料和生成報告的程式語言
awk 可以在命令列中進行一些簡單的操作,也可以被寫成指令碼來處理較大的應用問題
awkgrepsed 結合使用,將使 shell 程式設計更加容易

Linux 下使用的awkgawk

awk 逐行掃描輸入 (可以是檔案或管道等),按給定的模式查詢出匹配的行,然後對這些行執行awk 命令指定的操作。

與 sed一樣,awk不會修改輸入檔案的內容

可以使用重定向awk的輸出儲存到檔案中。


(一)awk簡單用法

用法示

 

選項 

-F

                       指定輸入記錄欄位的分隔符,預設使用環境變數IFS的值

-f

                          從指定檔案讀取awk_script

-v 

                             為awk設定變數


The IFS is a special shell variable.
You can change the value of IFS as per your requirments.
The Internal Field Separator (IFS) that is used for word splitting after expansion and to split lines into words with the read builtin command.
The default value is <space><tab><newline>. You can print it with the following command:
cat -etv <<<"$IFS"
IFS variable is commonly used with read command, parameter expansions and command substitution.


awk -F: '{ print $1 }' /etc/passwd

awk -F: '{ print $1, $3 }' /etc/passwd   // 輸出以空格連線

awk -F: '{ print $1 "|" $3 }' /etc/passwd  // 輸出以 | 連線

awk -F: '/root/{ print $1 "|" $3 }' /etc/passwd

awk -F: '/^root/' /etc/passwd   // 開頭是root 的行


(二)awk_script語法

注意BEGIN和END都是大寫字母

awk  'BEGIN {actions}

     /pattern1/{actions}

      ......

     /patternN/{actions}

     END {actions}'  input_file

其中BEGIN{actions} END{actions}是可選的

awk_script 可以由一條或多條 awk_cmd 組成,每條 awk_cmd 各佔一行。
每個 awk_cmd 由兩部分組成:/pattern/{actions}
awk_cmd 中的 /pattern/ 和 {actions} 可以省略,但不能同時省略;/pattern/ 省略時表示對所有的輸入行執行指定的 actions;
{actions} 省略時表示列印整行。

(三)awk 的執行過程



取出ip 地址:

ifconfigawk '/inet addr/{ print $2 }' | awk -F: '{ print $2 }'

ifconfigawk '/inet addr/{ print $2 }' | awk -F: 'BEGIN { print "begin..."} { print $2 } END { print "end..."} '


(四)模式匹配

使用正規表示式:/rexp/,如/^A/、/A[0-9]*/

^

                             只匹配行首 ( 可以看成是行首的標誌 )

$

                       只匹配行尾 ( 可以看成是行尾的標誌 )

                       一個單字元後緊跟 *,匹配 0個或多個此字元

[ ] 

                 匹配 [] 內的任意一個字元 ([^]反向匹配 )

\  

                     用來遮蔽一個元字元的特殊含義

.

                   匹配任意單個字元

str1|str2

                  匹配 str1str2

+                                                                                       

                      匹配一個或多個前一字元

?

                      匹配零個或一個前一字元

( )

                     字元組




(五)欄位分隔符、重定向和管道

NR表示從awk開始執行後,按照記錄分隔符讀取的資料次數,預設的記錄分隔符為換行符,因此預設的就是讀取的資料行數,

NR可以理解為Number of Record的縮寫。

在awk處理多個輸入檔案的時候,在處理完第一個檔案後,NR並不會從1開始,而是繼續累加,因此就出現了FNR

每當處理一個新檔案的時候,FNR就從1開始計數,FNR可以理解為File Number of Record。

NF表示目前的記錄被分割的欄位的數目,NF可以理解為Number of Field。



(六)更多awk

awk不僅是一個命令,它更是一個程式語言
變數
內部變數
     awk ' {print NR,$0} ' #給檔案加上行號
自定變數
函式
內建函式
自定義函式
     awk '{ print sum($1,$2) } function sum(x,y) { s=x+y ; return s }' grade.txt
陣列
     awk 'BEGIN { print split("123#456",arr,"#") ; for (i in arr) { print arr[i] } }'  // arr: 123 456

result="id 10 28 19 32"

data=(`echo $result | awk '{ for(i=2;i<=NF;i++) {print $i}}'`)

for task_id in ${data[@]}

do

done



參考:
《鳥哥的Linux私房菜基礎篇》
《高階bash shell程式設計指南》

http://www.grymoire.com/

相關文章