awk内置字元串函數
gsub(r,s) 在整個$0中用s替代r;gsub(r,s,t) 在整個t中用s替代r
gsub函數有點類似于sed查找和替換。它允許替換一個字元串或字元為另一個字元串或字元,并以正規表達式的形式執行。第一個函數作用于記錄$0,第二個gsub函數允許指定目标,然而,如果未指定目标,預設為$0。
index(s,t):函數傳回目标字元串s中查詢字元串t的首位置。
length(s) :傳回s長度
match(s,r): 測試s是否包含比對r的字元串
split(s,a,fs) 在fs上将s分成序列a
sprint (fmt,exp) :函數類似于printf函數(以後涉及),傳回基本輸出格式fmt的結果字元串exp。
sub(r,s) 用$0中最左邊最長的子串代替s
substr(s,p) 傳回字元串s中從p開始的字尾部分
substr(s,p,n) 傳回字元串s中從p開始長度為n的字尾部分。
match函數測試字元串s是否包含一個正規表達式r定義的比對。
split使用域分隔符fs将字元串s劃分為指定序列a。
1.gsub
要在整個記錄中替換一個字元串為另一個,使用正規表達式格式, /目标模式/,替換模式/。例如改變學生序号4842到4899:
$cat grade.txt
m.tans 5/99 48311 green 8 40 44
j.lulu 06/99 48317 green 9 24 26
p.bunny 02/99 48 yellow 12 35 28
j.troll 07/99 4842 brown-3 12 26 26
l.tansl 05/99 4712 brown-2 12 30 28
# cd /usr/sam
# awk 'gsub(/4842/,4899){print $0}' grade.txt
j.troll 07/99 4899 brown-3 12 26 26
2. index
查詢字元串s中t出現的第一位置。必須用雙引号将字元串括起來。例如傳回目标字元串bunny中ny出現的第一位置,即字元個數。
# awk 'begin {print index("bunny","ny")}' grade.txt
4
3. length
傳回所需字元串長度,例如檢驗字元串j.troll傳回名字及其長度,即人名構成的字元個數
# awk '$1=="j.troll" {print length($1)" "$1}' grade.txt
7 j.troll
還有一種方法,這裡字元串加雙引号。
# awk 'begin{print length("a few good men")}'
14
4. match
match測試目标字元串是否包含查找字元的一部分。可以對查找部分使用正規表達式,傳回值為成功出現的字元排列數。如果未找到,傳回0,第一個例子在ancd中查找d。因其不存在,是以傳回0。第二個例子在ancd中查找d。因其存在,是以傳回ancd中d出現的首位置字元數。第三個例子在學生j.lulu中查找u。
# awk 'begin{print match("ancd",/d/)}'
# awk '$1=="j.lulu" {print match($1,"u")}' grade.txt
5. split
使用split傳回字元串數組元素個數。工作方式如下:如果有一字元串,包含一指定分隔符-,例如ad2-kp9-ju2-lp-1,将之劃分成一個數組。使用split,指定分隔符及數組名。此例中,指令格式為("ad2-kp9-ju2-lp-1",parts_array,"-"),split然後傳回數組下标數,這裡結果為4。
# awk 'begin {print split("123-456-789",pats_array,"-")}'
3
還有一個例子使用不同的分隔符。
# awk 'begin {print split("123#456#789",myarray,"#")}'
這個例子中,split傳回數組myarray的下标數。數組myarray取值如下:
myarray[1]=123
myarray[2]=456
myarray[3]=789
6. sub
使用sub發現并替換模式的第一次出現位置。字元串str包含'poped popo pill',執行下列sub指令sub(/op/,"op",str)。模式op第一次出現時,進行替換操作,傳回結果如下:'poped pope pill'。
如:學生j.troll的記錄有兩個值一樣,"目前級别分"與"最進階别分"。隻改變第一個為29,第二個仍為26不動,操作指令為sub(/26/,"29",$0),隻替換第一個出現26的位置。注意j.troll記錄需存在。
# awk '$1=="j.troll" sub(/26/,"29",$0)' grade.txt
j.lulu 06/99 48317 green 9 24 29
j.troll 07/99 4842 brown-3 12 29 26
l.tansl 05/99 4712 brown-2 12 30 28
7. substr
substr是一個很有用的函數。它按照起始位置及長度傳回字元串的一部分。例子如下:
# awk '$1=="l.tansl" {print substr($1,1,3)}' grade.txt
l.t
上面例子中,指定在域1的第一個字元開始,傳回其前面3個字元。
如果給定長度值遠大于字元串長度, awk将從起始位置傳回所有字元,要抽取ltansl-ey的姓,隻需從第3個字元開始傳回長度為7。可以輸入長度99,awk傳回結果相同。
# awk '$1=="l.tansl" {print substr($1,1,99)}' grade.txt
l.tansl
substr的另一種形式是傳回字元串字尾或指定位置後面字元。這裡需要給出指定字元串及其傳回字串的起始位置。例如,從文本檔案中抽取姓氏,需操作域1,并從第三個字元開始:
# awk '{print substr($1,3)}' grade.txt
tans
lulu
bunny
troll
tansl
還有一個例子,在begin部分定義字元串,在end部分傳回從第t個字元開始抽取的子串。
# awk 'begin{str="a few good men"}end{print substr(str,7)}' grade.txt
good men
8. 從shell中向awk傳入字元串
awk腳本大多隻有一行,其中很少是字元串表示的。大多要求在一行内完成awk腳本,這一點通過将變量傳入awk指令行會變得很容易。現就其基本原理講述一些例子。
使用管道将字元串stand-by傳入awk,傳回其長度。
# echo "stand-by" | awk '{print length($0)}'
8
設定檔案名為一變量,管道輸出到awk,傳回不帶擴充名的檔案名。
# str="mydoc.txt"
# echo $str|awk '{print substr($str,1,5)}'
mydoc
設定檔案名為一變量,管道輸出到awk,隻傳回其擴充名。
# echo $str|awk '{print substr($str,7)}'
txt
字元串屏蔽序列
使用字元串或正規表達式時,有時需要在輸出中加入一新行或查詢一進制字元。列印一新行時(新行為字元\n),給出其屏蔽序列,以不失其特殊含義,用法為在字元串前加入反斜線。例如使用\n強迫列印一新行。
如果使用正規表達式,查詢花括号({ }),在字元前加反斜線,如/\{/,将在awk中失掉其特殊含義。
awk中使用的屏蔽序列
\b 倒退鍵
\t tab鍵
\f 走紙換頁
\ddd 八進制值
\n 新行
\c 任意其他特殊字元,例如\ \為反斜線符号
\r Enter鍵
使用上述符号,列印may day,中間夾tab鍵,後跟兩個新行,再列印may day,但這次使用八進制數104、141、171分别代表d、a、y。
# awk 'begin {print"\nmay\tday\n\nmay\t\104\141\171"}'
may day
注意,\104為d的八進制ascii碼,\141為a的八進制ascii碼,等等。
awk輸出函數printf
目前為止,所有例子的輸出都是直接到螢幕,除了tab鍵以外沒有任何格式。awk提供函數printf,擁有幾種不同的格式化輸出功能。例如按列輸出、左對齊或右對齊方式。
每一種printf函數(格式控制字元)都以一個%符号開始,以一個決定轉換的字元結束.轉換包含三種修飾符。
printf函數基本文法是printf([格式控制符],參數),格式控制字元通常在引号裡。
printf修飾符
- 左對齊
width 域的步長,用0表示0步長
.prec 最大字元串長度,或小數點右邊的位數
awk printf格式
%c ascii字元
%d 整數
%e 浮點數,科學記數法
%f 浮點數,例如(1 2 3 . 4 4)
%g awk決定使用哪種浮點數轉換e或者f
%o 八進制數
%s 字元串
%x 十六進制數
1. 字元轉換
觀察ascii碼中65的等價值。管道輸出65到awk。printf進行ascii碼字元轉換。這裡也加入換行,因為預設情況下printf不做換行動作。
$echo "65" | awk '{printf "%c\n",$0}'
a
按同樣方式使用awk得到同樣結果。
$awk 'begin{printf "%c\n",65}'
所有的字元轉換都是一樣的,下面的例子表示進行浮點數轉換後'999'的輸出結果。整數傳入後被加了六個小數點。
$awk 'begin{printf "%f\n",999}'
999.000000
2. 格式化輸出
列印所有的學生名字和序列号,要求名字左對齊, 15個字元長度,後跟序列号。注意\n換行符放在最後一個訓示符後面。輸出将自動分成兩列。
# awk '{printf "%-15s %s\n",$1,$3}' grade.txt
m.tans 48311
j.lulu 48317
p.bunny 48
j.troll 4842
l.tansl 4712
加入一些文本注釋幫助了解封包含義。可在正文前嵌入頭資訊。注意這裡使用print加入頭資訊。如果願意,也可使用printf。
# awk 'begin{print "name\t\ts.number"}{printf "%-15s %s\n",$1,$3}' grade.txt
name s.number
列印輸出“what is your name?" 利用getline函數從終端接收輸入,并傳送給name變量,直到使用者輸入回車為止,如果第一域比對employees2中的記錄。
列印“found ",name變量,"on line" ,行号。
列印“see ya, ”,name變量
以上是傳入name變量的值存在于employees2中的情況
$ awk 'begin{printf "what is your name?" ;\
getline name < "/dev/tty"}\
$1 ~ name {print "found " name " on line ",nr "."}\
end{print "see ya, " name "."}' employees2
what is your name?tom
found tom on line 1.
see ya, tom.
不存在于employees2中的情況
what is your name?czm
see ya, czm.
參考至:《unix® shells by example fourth edition》by ellie quigley
《linux與unix shell程式設計指南》
http://blog.sina.com.cn/s/blog_45b28bfb0100o0fs.html
本文為原創文章,轉載請注明出處、作者
如有錯誤,歡迎指正
作者:czmmiao 文章出處:http://czmmiao.iteye.com/blog/1885280