1. 程式人生 > >linux常用技巧

linux常用技巧

和sed一樣,awk也是逐行掃描檔案的,從第一行到最後一行,尋找匹配特定模板的行,並在這些行上執行“選擇”動作。如果一個模板沒有指定動作,這些匹配的行就被顯示在螢幕上。如果一個動作沒有模板,所有被動作指定的行都被處理。 1. awk的基本格式: /> awk 'pattern' filename /> awk '{action}' filename /> awk 'pattern {action}' filename 具體應用方式分別見如下三個用例: /> cat employees Tom Jones 4424 5/12/66 543354 Mary Adams 5346 11/4/63 28765 Sally Chang 1654 7/22/54 650000 Billy Black 1683 9/23/44 336500 /> awk '/Mary/' employees #列印所有包含模板Mary的行。 Mary Adams 5346 11/4/63 28765 #列印檔案中的第一個欄位,這個域在每一行的開始,預設由空格或其它分隔符。 /> awk '{print $1}' employees Tom Mary Sally Billy /> awk '/Sally/{print $1, $2}' employees #列印包含模板Sally的行的第一、第二個域欄位。 Sally Chang 2. awk的格式輸出: awk中同時提供了print和printf兩種列印輸出的函式,其中print函式的引數可以是變數、數值或者字串。字串必須用雙引號引用,引數用逗號分隔。如果沒有逗號,引數就串聯在一起而無法區分。這裡,逗號的作用與輸出檔案的分隔符的作用是一樣的,只是後者是空格而已。下面給出基本的轉碼序列:

轉碼含義\n換行\r回車\t製表符

/> date | awk '{print "Month: " $2 "\nYear: ", $6}' Month: Oct Year: 2011 /> awk '/Sally/{print "\t\tHave a nice day, " $1,$2 "\!"}' employees Have a nice day, Sally Chang! 在列印數字的時候你也許想控制數字的格式,我們通常用printf來完成這個功能。awk的特殊變數OFMT也可以在使用print函式的時候,控制數字的列印格式。它的預設值是"%.6g"----小數點後面6位將被列印。 /> awk 'BEGIN { OFMT="%.2f"; print 1.2456789, 12E-2}' 1.25 0.12 現在我們介紹一下功能更為強大的printf函式,其用法和c語言中printf基本相似。下面我們給出awk中printf的格式化說明符列表:

格式化說明符功能示例結果%c列印單個ASCII字元。printf("The character is %c.\n",x)The character is A.%d列印十進位制數。printf("The boy is %d years old.\n",y)The boy is 15 years old.%e列印用科學記數法表示的數。printf("z is %e.\n",z)z is 2.3e+01.%f列印浮點數。printf("z is %f.\n",z)z is 2.300000%o列印八進位制數。printf("y is %o.\n",y)y is 17.%s列印字串。printf("The name of the culprit is %s.\n",$1);The name of the culprit is Bob Smith.%x列印十六進位制數。printf("y is %x.\n",y)y is f.

注:假設列表中的變臉值為x = A, y = 15, z = 2.3, $1 = "Bob Smith" /> echo "Linux" | awk '{printf "|%-15s|\n", $1}' # %-15s表示保留15個字元的空間,同時左對齊。 |Linux | /> echo "Linux" | awk '{printf "|%15s|\n", $1}' # %-15s表示保留15個字元的空間,同時右對齊。 | Linux| #%8d表示數字右對齊,保留8個字元的空間。 /> awk '{printf "The name is %-15s ID is %8d\n", $1,$3}' employees The name is Tom ID is 4424 The name is Mary ID is 5346 The name is Sally ID is 1654 The name is Billy ID is 1683 3. awk中的記錄和域: awk中預設的記錄分隔符是回車,儲存在其內建變數ORS和RS中。$0變數是指整條記錄。 /> awk '{print $0}' employees #這等同於print的預設行為。 Tom Jones 4424 5/12/66 543354 Mary Adams 5346 11/4/63 28765 Sally Chang 1654 7/22/54 650000 Billy Black 1683 9/23/44 336500 變數NR(Number of Record),記錄每條記錄的編號。 /> awk '{print NR, $0}' employees 1 Tom Jones 4424 5/12/66 543354 2 Mary Adams 5346 11/4/63 28765 3 Sally Chang 1654 7/22/54 650000 4 Billy Black 1683 9/23/44 336500 變數NF(Number of Field),記錄當前記錄有多少域。 /> awk '{print $0,NF}' employees Tom Jones 4424 5/12/66 543354 5 Mary Adams 5346 11/4/63 28765 5 Sally Chang 1654 7/22/54 650000 5 Billy Black 1683 9/23/44 336500 5 #根據employees生成employees2。sed的用法可以參考上一篇blog。 /> sed 's/[[:space:]]\+\([0-9]\)/:\1/g;w employees2' employees /> cat employees Tom Jones:4424:5/12/66:543354 Mary Adams:5346:11/4/63:28765 Sally Chang:1654:7/22/54:650000 Billy Black:1683:9/23/44:336500 /> awk -F: '/Tom Jones/{print $1,$2}' employees2 #這裡-F選項後面的字元表示分隔符。 Tom Jones 4424 變數OFS(Output Field Seperator)表示輸出欄位間的分隔符,預設是空格。 /> awk -F: '{OFS = "?"}; /Tom/{print $1,$2 }' employees2 #在輸出時,域欄位間的分隔符已經是?(問號)了 Tom Jones?4424 對於awk而言,其模式部分將控制這動作部分的輸入,只有符合模式條件的記錄才可以交由動作部分基礎處理,而模式部分不僅可以寫成正則表示式(如上面的例子),awk還支援條件表示式,如: /> awk '$3 < 4000 {print}' employees Sally Chang 1654 7/22/54 650000 Billy Black 1683 9/23/44 336500 在花括號內,用分號分隔的語句稱為動作。如果模式在動作前面,模式將決定什麼時候發出動作。動作可以是一個語句或是一組語句。語句之間用分號分隔,也可以用換行符,如: pattern { action statement; action statement; etc. } or pattern { action statement action statement } 模式和動作一般是捆綁在一起的。需要注意的是,動作是花括號內的語句。模式控制的動作是從第一個左花括號開始到第一個右花括號結束,如下: /> awk '$3 < 4000 && /Sally/ {print}' employees Sally Chang 1654 7/22/54 650000 4. 匹配操作符: " ~ " 用來在記錄或者域內匹配正則表示式。 /> awk '$1 ~ /[Bb]ill/' employees #顯示所有第一個域匹配Bill或bill的行。 Billy Black 1683 9/23/44 336500 /> awk '$1 !~ /[Bb]ill/' employees #顯示所有第一個域不匹配Bill或bill的行,其中!~表示不匹配的意思。 Tom Jones 4424 5/12/66 543354 Mary Adams 5346 11/4/63 28765 Sally Chang 1654 7/22/54 650000 5. awk的基本應用例項: /> cat testfile northwest NW Charles Main 3.0 .98 3 34 western WE Sharon Gray 5.3 .97 5 23 southwest SW Lewis Dalsass 2.7 .8 2 18 southern SO Suan Chin 5.1 .95 4 15 southeast SE Patricia Hemenway 4.0 .7 4 17 eastern EA TB Savage 4.4 .84 5 20 northeast NE AM Main Jr. 5.1 .94 3 13 north NO Margot Weber 4.5 .89 5 9 central CT Ann Stephens 5.7 .94 5 13 /> awk '/^north/' testfile #列印所有以north開頭的行。 northwest NW Charles Main 3.0 .98 3 34 northeast NE AM Main Jr. 5.1 .94 3 13 north NO Margot Weber 4.5 .89 5 9 /> awk '/^(no|so)/' testfile #列印所有以so和no開頭的行。 northwest NW Charles Main 3.0 .98 3 34 southwest SW Lewis Dalsass 2.7 .8 2 18 southern SO Suan Chin 5.1 .95 4 15 southeast SE Patricia Hemenway 4.0 .7 4 17 northeast NE AM Main Jr. 5.1 .94 3 13 north NO Margot Weber 4.5 .89 5 9 /> awk '$5 ~ /\.[7-9]+/' testfile #第五個域欄位匹配包含.(點),後面是7-9的數字。 southwest SW Lewis Dalsass 2.7 .8 2 18 central CT Ann Stephens 5.7 .94 5 13 /> awk '$8 ~ /[0-9][0-9]$/{print $8}' testfile #第八個域以兩個數字結束的列印。 34 23 18 15 17 20 13 十. awk表示式功能: 1. 比較表示式: 比較表示式匹配那些只在條件為真時才執行的行。這些表示式利用關係運算符來比較數字和字串。見如下awk支援的條件表示式列表:

運算子含義例子<小於x < y<=小於等於x <= y==等於x == y!=不等於x != y>=大於等於x >= y>大於x > y~匹配x ~ /y/!~不匹配x !~ /y/

/> cat employees Tom Jones 4424 5/12/66 543354 Mary Adams 5346 11/4/63 28765 Sally Chang 1654 7/22/54 650000 Billy Black 1683 9/23/44 336500 /> awk '$3 == 5346' employees #列印第三個域等於5346的行。 Mary Adams 5346 11/4/63 28765 /> awk '$3 > 5000 {print $1}' employees #列印第三個域大於5000的行的第一個域欄位。 Mary /> awk '$2 ~ /Adam/' employess #列印第二個域匹配Adam的行。 Mary Adams 5346 11/4/63 28765 2. 條件表示式: 條件表示式使用兩個符號--問號和冒號給表示式賦值: conditional expression1 ? expression2 : expressional3,其邏輯等同於C語言中的條件表示式。其對應的if/else語句如下: { if (expression1) expression2 else expression3 } /> cat testfile northwest NW Charles Main 3.0 .98 3 34 western WE Sharon Gray 5.3 .97 5 23 southwest SW Lewis Dalsass 2.7 .8 2 18 southern SO Suan Chin 5.1 .95 4 15 southeast SE Patricia Hemenway 4.0 .7 4 17 eastern EA TB Savage 4.4 .84 5 20 northeast NE AM Main Jr. 5.1 .94 3 13 north NO Margot Weber 4.5 .89 5 9 central CT Ann Stephens 5.7 .94 5 13 /> awk 'NR <= 3 {print ($7 > 4 ? "high "$7 : "low "$7) }' testfile low 3 high 5 low 2 3. 數學表示式: 運算可以在模式內進行,其中awk將所有的運算都視為浮點運算,見如下列表:

運算子含義例子+加x + y-減x - y*乘x * y/除x / y%取餘x % y^乘方x ^ y

/> awk '/southern/{print $5 + 10}' testfile #如果記錄包含正則表示式southern,第五個域就加10並列印。 15.1 /> awk '/southern/{print $8 /2 }' testfile #如果記錄包含正則表示式southern,第八個域除以2並列印。 7.5 4. 邏輯表示式: 見如下列表:

運算子含義例子&&邏輯與a && b||邏輯或a || b!邏輯非!a

/> awk '$8 > 10 && $8 < 17' testfile #打印出第八個域的值大於10小於17的記錄。 southern SO Suan Chin 5.1 .95 4 15 central CT Ann Stephens 5.7 .94 5 13 #列印第二個域等於NW,或者第一個域匹配south的行的第一、第二個域。 /> awk '$2 == "NW" || $1 ~ /south/ {print $1,$2}' testfile northwest NW southwest SW southern SO southeast SE /> awk '!($8 > 13) {print $8}' testfile #列印第八個域欄位不大於13的行的第八個域。 3 9 13 5. 範圍模板: 範圍模板匹配從第一個模板的第一次出現到第二個模板的第一次出現,第一個模板的下一次出現到第一個模板的下一次出現等等。如果第一個模板匹配而第二個模板沒有出現,awk就顯示到檔案末尾的所有行。 /> awk '/^western/,/^eastern/ {print $1}' testfile #列印以western開頭到eastern開頭的記錄的第一個域。 western WE southwest SW southern SO southeast SE eastern EA 6. 賦值符號: #找到第三個域等於Ann的記錄,然後給該域重新賦值為Christian,之後再列印輸出該記錄。 /> awk '$3 == "Ann" { $3 = "Christian"; print}' testfile central CT Christian Stephens 5.7 .94 5 13 /> awk '/Ann/{$8 += 12; print $8}' testfile #找到包含Ann的記錄,並將該條記錄的第八個域的值+=12,最後