sed和awk
背景
設計script時,有時候需要修改腳步,如刪除或置換某些關鍵詞。這種在script執行過程動態修改檔案的做法,稱為流編輯。具有流編輯能力的工具,稱為流編輯器(stream editor)。sed是這方面的佼佼者,可補bash的不足。另外,script執行時可能要製作報表,呈現各種欄位資訊。傳統上,能和bash完美搭配的,非awk莫屬。
Regex
Regex是組成“樣式”的基本文法,而“樣式”是運用sed和awk必備的能力。sed和awk相同的運行方式是:只要符合“樣式”的資料行,就對它執行指定的“操作”。
有關Regex的文章很多。可參見:http://www.cnblogs.com/KissKnife/archive/2008/03/23/1118423.html
sed的用法
sed是一種非互動流編輯器,可動態編輯檔案。sed的工作模式是,比對每一資料行,若符合樣式,就執行指定的操作。
文法
sed '樣式命令' 檔案
“樣式”使用一對//含括,表示尋找之意;也可以指定資料行的範圍。
sed並不會變更檔內容。sed的工作方式是讀取檔案內容,經流編輯之後,把結果顯示到標準輸出。因此,如果想要儲存sed的處理結果,得自行運用轉向輸出將結果存成其他檔案。
各種用法
1 刪除某一段範圍的資料行:sed '1,4d' datafl 把第1到4行資料刪除,剩下的顯示出來。d表示刪除
2 把含有“樣式”的資料行刪除:sed '/La/d' datafl 把含有La的行刪除,剩下的顯示出來。//代表搜尋
sed '/[0-9]\{3\}/d' datafl 把含有3位元的行刪除,剩下的顯示出來。。 Regex的應用
3 不含有“樣式”的資料行刪除:sed '/La/!d' datafl 把不含有La的行刪除,剩下的顯示出來
4 含有“樣式”的資料行顯示出來:sed '/La/p' datafl 把含有La的行顯示出來。但sed預設也會把不符合的資料行顯示出來,所以應這樣用:sed -n '/La/p' datafl -n會抑制sed顯示
5 取代:sed -n 's/La/Oo/p' datafl s表示選取,第一對//中包括的字串是搜尋的目標,第二對//包括的是置換的字串。它會把資料行中的La換成Oo 但這樣只會更換第一個出現的La,若要全部置換,應使用:sed -n 's/La/Oo/gp' dafl
6 取用符合樣式的字串:sed -n 's/\(La\)/\1Oo/p' datafl 把找到的La存起來,用\1取回來再使用。執行的結果是,如資料行含有La,則第一個出現的La會置換成LaOo,然後顯示這些含有La的資料行
7 找到符合樣式的資料行後,再進行取代的操作:sed -n '/AAA/s/234/567/p' datafl 找到含AAA的那一行之後,將234換成567 sed -n '/AAA/,/DDD/s/B/567/p' datafl 將含有AAA到含有DDD的那幾行,皆將其中的B換成567
例子
#!/bin/bash
if [ $# -ne 1 ] ; then
echo "Usage: $0 on 或 $0 off"
exit 1
fi
OPT=$1
case "$OPT" in
[Oo][Nn]) CMD='YES';;
[Oo][Ff][Ff]) CMD='NO';;
*)
echo '選項錯誤:使用on或off'
exit 1;;
esac
VSFTP_conf='/etc/vsftpd.conf'
TMP_file="/tmp/tmp.$$"
if [ -e $VSFTP_conf ] ; then
sed s/^.anonymous_enable=.*/anonymous_enable=$CMD/ $VSFTP_conf > $TMP_file
mv -f $TMP_file $VSFTP_conf
echo '設定成功'
else
echo "檔案:$VSFTP_conf 不存在"
fi
awk的用法
awk是一種可以處理資料,產生個時候報表的語言。工作方式是讀取資料檔案,將每一行資料視為一條記錄,每筆記錄以欄位分割符分成若干欄位,然後輸出各個欄位的值。
ps auxw | awk '{print $2}'
awk對每一條記錄都會套用一個“樣式{操作}”,如果符合樣式,就執行指定的操作。樣式或操作之一,可以省略。如果只有樣式,表示要顯示符合樣式的資料行;如果只有操作,表示對每一資料行都執行該項操作。
以下是awk常用的作用格式:
awk “樣式” 檔案 :把符合樣式的資料行顯示出來
awk '{操作}' 檔案 :對每一行都執行{}中的操作
awk '樣式{操作}' 檔案 :對符合樣式的資料行,執行{}中的操作
awk的用法:
1 awk '/La/' datafl 顯示含有La的資料行
2 awk '{print $1,$2}' datafl 顯示datafl每一行的第1和第2個欄位
3 awk '/La/{print $1,$2}' datafl 將含有關鍵詞La的資料行的第1及第2個欄位顯示
4 awk -F: '/^ols3/{print $3,$4}' /etc/passwd 使用選項-F 指定:為分隔字元,帳號ols3的uid及gid欄位顯示出來
5 awk -F: 'BEGIN{OFS="+++"}/^ols3/{print $1,$2,$3,$4,$5}' /etc/passwd 以:為分隔字元,+++為輸出欄位分隔符號,將帳號ols3的第1-5欄位顯示 BEGIN{}地區指定awk一開始先做初始化操作,設定OFS="+++"。變了OFS的作用是儲存輸出欄位的分隔字元。