Linux Shell常用技巧(五)
十一.? awk編程:
??? 1.? 變量:
????在awk中變量無須定義即可使用,變量在賦值時即已經完成了定義。變量的類型可以是數字、字符串。根據使用的不同,未初始化變量的值為0或空白字符串" ",這主要取決于變量應用的上下文。下面為變量的賦值負號列表:
| 符號 | 含義 | 等價形式 |
| = | a = 5 | a = 5 |
| += | a = a + 5 | a += 5 |
| -= | a = a - 5 | a -= 5 |
| *= | a = a * 5 | a *= 5 |
| /= | a = a / 5 | a /= 5 |
| %= | a = a % 5 | a %= 5 |
| ^= | a = a ^ 5 | a ^= 5 |
??? /> awk '$1 ~ /Tom/ {Wage = $2 * $3; print Wage}' filename
?? ?該命令將從文件中讀取,并查找第一個域字段匹配Tom的記錄,再將其第二和第三個字段的乘積賦值給自定義的Wage變量,最后通過print命令將該變量打印輸出。
??? /> awk ' {$5 = 1000 * $3 / $2; print}' filename
?? ?在上面的命令中,如果$5不存在,awk將計算表達式1000 * $3 / $2的值,并將其賦值給$5。如果第五個域存在,則用表達式覆蓋$5原來的值。
?? ?我們同樣也可以在命令行中定義自定義的變量,用法如下:
??? /> awk -F: -f awkscript month=4 year=2011 filename
?? ?這里的month和year都是自定義變量,且分別被賦值為4和2000,在awk的腳本中這些變量將可以被直接使用,他們和腳本中定義的變量在使用上沒有任何區別。
?? ?除此之外,awk還提供了一組內建變量(變量名全部大寫),見如下列表:
| 變量名 | 變量內容 |
| ARGC | 命令行參數的數量。 |
| ARGIND | 命令行正在處理的當前文件的AGV的索引。 |
| ARGV | 命令行參數數組。 |
| CONVFMT | 轉換數字格式。 |
| ENVIRON | 從shell中傳遞來的包含當前環境變量的數組。 |
| ERRNO | 當使用close函數或者通過getline函數讀取的時候,發生的重新定向錯誤的描述信息就保存在這個變量中。 |
| FIELDWIDTHS | 在對記錄進行固定域寬的分割時,可以替代FS的分隔符的列表。 |
| FILENAME | 當前的輸入文件名。 |
| FNR | 當前文件的記錄號。 |
| FS | 輸入分隔符,默認是空格。 |
| IGNORECASE | 在正則表達式和字符串操作中關閉大小寫敏感。 |
| NF | 當前文件域的數量。 |
| NR | 當前文件記錄數。 |
| OFMT | 數字輸出格式。 |
| OFS | 輸出域分隔符。 |
| ORS | 輸出記錄分隔符。 |
| RLENGTH | 通過match函數匹配的字符串的長度。 |
| RS | 輸入記錄分隔符。 |
| RSTART | 通過match函數匹配的字符串的偏移量。 |
| SUBSEP | 下標分隔符。 |
??? /> cat employees2
?? ?Tom Jones:4424:5/12/66:543354
?? ?Mary Adams:5346:11/4/63:28765
?? ?Sally Chang:1654:7/22/54:650000
?? ?Mary Black:1683:9/23/44:336500
??? /> awk -F: '{IGNORECASE = 1}; $1 == "mary adams" { print NR, $1, $2, $NF}' employees2
?? ?2 Mary Adams 5346 28765
??? /> awk -F: ' $1 == "mary adams" { print NR, $1, $2, $NF}' employees2
??? 沒有輸出結果。
?? ?當IGNORECASE內置變量的值為非0時,表示在進行字符串操作和處理正則表達式時關閉大小寫敏感。這里的"mary adams"將匹配文件中的"Mary Admams"記錄。最后print打印出第一、第二和最后一個域。需要說明的是NF表示當前記錄域的數量,因此$NF將表示最后一個域的值。
?? ?awk在動作部分還提供了BEGIN塊和END塊。其中BEGIN動作塊在awk處理任何輸入文件行之前執行。事實上,BEGIN塊可以在沒有任何輸入文件的條件下測試。因為在BEGIN塊執行完畢以前awk將不讀取任何輸入文件。BEGIN塊通常被用來改變內建變量的值,如OFS、RS或FS等。也可以用于初始化自定義變量值,或打印輸出標題。
??? /> awk 'BEGIN {FS = ":"; OFS = "\t"; ORS = "\n\n"} { print $1,$2,$3} filename
?? ?上例中awk在處理文件之前,已經將域分隔符(FS)設置為冒號,輸出文件域分隔符(OFS)設置為制表符,輸出記錄分隔符(ORS)被設置為兩個換行符。BEGIN之后的動作模塊中如果有多個語句,他們之間用分號分隔。
?? ?和BEGIN恰恰相反,END模塊中的動作是在整個文件處理完畢之后被執行的。
??? /> awk 'END {print "The number of the records is " NR }' filename
?? ?awk在處理輸入文件之后,執行END模塊中的動作,上例中NR的值是讀入的最后一個記錄的記錄號。
??? /> awk '/Mary/{count++} END{print "Mary was found " count " times." }' employees2
?? ?Mary was found 2 times.
??? /> awk '/Mary/{count++} END{print "Mary was found " count " times." }' employees2
?? ?Mary was found 2 times.
?? ?
?? ?/> 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/{count += 1; print count}' testfile?? ? #如記錄以正則north開頭,則創建變量count同時增一,再輸出其值。
?? ?1
?? ?2
?? ?3
?? ?
?? ?#這里只是輸出前三個字段,其中第七個域先被賦值給變量x,在自減一,最后再同時打印出他們。
?? ?/> awk 'NR <= 3 {x = $7--; print "x = " x ", $7 = " $7}' testfile
?? ?x = 3, $7 = 2
?? ?x = 5, $7 = 4
?? ?x = 2, $7 = 1?? ?
?? ?
?? ?#打印NR(記錄號)的值在2--5之間的記錄。
?? ?/> awk 'NR == 2,NR == 5 {print "The record number is " NR}' testfile
?? ?The record number is 2
?? ?The record number is 3
?? ?The record number is 4
?? ?The record number is 5
?? ?#打印環境變量USER和HOME的值。環境變量的值由父進程shell傳遞給awk程序的。
?? ?/> awk 'BEGIN { print ENVIRON["USER"],ENVIRON["HOME"]}'
?? ?root /root
?? ?
?? ?#BEGIN塊兒中對OFS內置變量重新賦值了,因此后面的輸出域分隔符改為了\t。
?? ?/> awk 'BEGIN { OFS = "\t"}; /^Sharon/{ print $1,$2,$7}' testfile
?? ?western WE????? 5
?? ?
?? ?#從輸入文件中找到以north開頭的記錄count就加一,最后在END塊中輸出該變量。
?? ?/> awk '/^north/{count++}; END{print count}' testfile
?? ?3
??? 2.? 重新定向:
????在動作語句中使用shell通用的重定向輸出符號">"就可以完成awk的重定向操作,當使用>的時候,原有文件將被清空,同時文件持續打開,直到文件被明確的關閉或者awk程序終止。來自后面的打印語句的輸出會追加到前面內容的后面。符號">>"用來打開一個文件但是不清空原有文件的內容,重定向的輸出只是被追加到這個文件的末尾。
?? ?/> awk '$4 >= 70 {print $1,$2 > "passing_file"}' filename? #注意這里的文件名需要用雙引號括起來。
??? #通過兩次cat的結果可以看出>和>>的區別。
?? ?/> awk '/north/{print $1,$3,$4 > "districts" }' testfile
?? ?/> cat districts
?? ?northwest Joel Craig
?? ?northeast TJ Nichols
?? ?north Val Shultz
?? ?/> awk '/south/{print $1,$3,$4 >> "districts" }' testfile
?? ?/> cat districts
?? ?northwest Joel Craig
?? ?northeast TJ Nichols
?? ?north Val Shultz
?? ?southwest Chris Foster
?? ?southern May Chin
?? ?southeast Derek Jonhson
???
?? ?awk中對于輸入重定向是通過getline函數來完成的。getline函數的作用是從標準輸入、管道或者當前正在處理的文件之外的其他輸入文件獲得輸入。他負責從輸入獲得下一行的內容,并給NF、NR和FNR等內建變量賦值。如果得到一個記錄,getline就返回1,如果達到文件末尾就返回0。如果出現錯誤,如打開文件失敗,就返回-1。
?? ?/> awk 'BEGIN { "date" | getline d; print d}'
?? ?Tue Nov 15 15:31:42 CST 2011
?? ?上例中的BEGIN動作模塊中,先執行shell命令date,并通過管道輸出給getline,然后再把輸出賦值給自定義變量d并打印輸出它。
?? ?
?? ?/> awk 'BEGIN { "date" | getline d; split(d,mon); print mon[2]}'
?? ?Nov
?? ?上例中date命令通過管道輸出給getline并賦值給d變量,再通過內置函數split將d拆分為mon數組,最后print出mon數組的第二個元素。
?? ?
?? ?/> awk 'BEGIN { while("ls" | getline) print}'
?? ?employees
?? ?employees2
?? ?testfile
?? ?命令ls的輸出傳遞給getline作為輸入,循環的每個反復,getline都從ls的結果中讀取一行輸入,并把他打印到屏幕。
?? ?
?? ?/> 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? Mary
?? ?Found Mary on line? 2.
?? ?See ya, Mary.?? ?
?? ?上例先是打印出BEGIN塊中的"What is your name? ",然后等待用戶從/dev/tty輸入,并將讀入的數據賦值給name變量,之后再從輸入文件中讀取記錄,并找到匹配輸入變量的記錄并打印出來,最后在END塊中輸出結尾信息。
?? ?
??? /> awk 'BEGIN { while(getline < "/etc/passwd" > 0) lc++; print lc}'
?? ?32
?? ?awk將逐行讀取/etc/passwd文件中的內容,在達到文件末尾之前,計數器lc一直自增1,當到了末尾后打印lc的值。lc的值為/etc/passwd文件的行數。
??? 由于awk中同時打開的管道只有一個,那么在打開下一個管道之前必須關閉它,管道符號右邊可以通過可以通過雙引號關閉管道。如果不關閉,它將始終保持打開狀態,直到awk退出。
?? ?/> awk {print $1,$2,$3 | "sort -4 +1 -2 +0 -1"} END {close("sort -4 +1 -2 +0 -1") } filename
??? 上例中END模塊中的close顯示關閉了sort的管道,需要注意的是close中關閉的命令必須和當初打開時的完全匹配,否則END模塊產生的輸出會和以前的輸出一起被sort分類。
??? 3.? 條件語句:
????awk中的條件語句是從C語言中借鑒來的,見如下聲明方式:
?? ?if (expression) {
?? ??? ?statement;
?? ??? ?statement;
?? ??? ?... ...
?? ?}
? ? /> awk '{if ($6 > 50) print $1 "Too hign"}' filename
?? ?/> awk '{if ($6 > 20 && $6 <= 50) { safe++; print "OK}}' filename
?? ?if (expression) {
?? ??? ?statement;
?? ?} else {
?? ??? ?statement2;
?? ?}
?? ?/> awk '{if ($6 > 50) print $1 " Too high"; else print "Range is OK" }' filename
?? ?/> awk '{if ($6 > 50) { count++; print $3 } else { x = 5; print $5 }' filename
?? ?if (expression) {
?? ??? ?statement1;
?? ?} else if (expression1) {
?? ??? ?statement2;
?? ?} else {
?? ??? ?statement3;
?? ?}
?? ?/> awk '{if ($6 > 50) print "$6 > 50" else if ($6 > 30) print "$6 > 30" else print "other"}' filename
???4.? 循環語句:
????awk中的循環語句同樣借鑒于C語言,支持while、do/while、for、break、continue,這些關鍵字的語義和C語言中的語義完全相同。
????5.? 流程控制語句:
????next語句是從文件中讀取下一行,然后從頭開始執行awk腳本。
?? ?exit語句用于結束awk程序。它終止對記錄的處理。但是不會略過END模塊,如果exit()語句被賦值0--255之間的參數,如exit(1),這個參數就被打印到命令行,以判斷退出成功還是失敗。
????6.? 數組:
????因為awk中數組的下標可以是數字和字母,數組的下標通常被稱為關鍵字(key)。值和關鍵字都存儲在內部的一張針對key/value應用hash的表格里。由于hash不是順序存儲,因此在顯示數組內容時會發現,它們并不是按照你預料的順序顯示出來的。數組和變量一樣,都是在使用時自動創建的,awk也同樣會自動判斷其存儲的是數字還是字符串。一般而言,awk中的數組用來從記錄中收集信息,可以用于計算總和、統計單詞以及跟蹤模板被匹配的次數等等。
?? ?/> 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 '{name[x++] = $2}; END{for (i = 0; i < NR; i++) print i, name[i]}' employees?? ?
?? ?0 Jones
?? ?1 Adams
?? ?2 Chang
?? ?3 Black
?? ?在上例中,數組name的下標是變量x。awk初始化該變量的值為0,在每次使用后自增1,讀取文件中的第二個域的值被依次賦值給name數組的各個元素。在END模塊中,for循環遍歷數組的值。因為下標是關鍵字,所以它不一定從0開始,可以從任何值開始。
?? ?#這里是用內置變量NR作為數組的下標了。
?? ?/> awk '{id[NR] = $3}; END {for (x = 1; x <= NR; x++) print id[x]}' employees
?? ?4424
?? ?5346
?? ?1654
?? ?1683
?? ?awk中還提供了一種special for的循環,見如下聲明:
?? ?for (item in arrayname) {
?? ??? ?print arrayname[item]
?? ?}
?? ?/> cat db
?? ?Tom Jones
?? ?Mary Adams
?? ?Sally Chang
?? ?Billy Black
?? ?Tom Savage
?? ?Tom Chung
?? ?Reggie Steel
?? ?Tommy Tucker
?? ?/> awk '/^Tom/{name[NR]=$1}; END {for(i = 1;i <= NR; i++) print name[i]}' db
?? ?Tom
?? ?Tom
?? ?Tom
?? ?Tommy
?? ?從輸出結果可以看出,只有匹配正則表達式的記錄的第一個域被賦值給數組name的指定下標元素。因為用NR作為下標,所以數組的下標不可能是連續的,因此在END模塊中用傳統的for循環打印時,不存在的元素就打印空字符串了。下面我們看看用special for的方式會有什么樣的輸出。
?? ?/> awk '/^Tom/{name[NR]=$1};END{for(i in name) print name[i]}' db
?? ?Tom
?? ?Tom
?? ?Tommy
?? ?Tom
?? ?下面我們看一下用字符串作為下標的例子:(如果下標是字符串文字常量,則需要用雙引號括起來)?? ?
?? ?/> cat testfile2
?? ?tom
?? ?mary
?? ?sean
?? ?tom
?? ?mary
?? ?mary
?? ?bob
?? ?mary
?? ?alex
? ? /> awk '/tom/{count["tom"]++}; /mary/{count["mary"]++}; END{print "There are " count["tom"] \
?? ??? ?" Toms and " count["mary"] " Marys in the file."} testfile2
?? ?There are 2 Toms and 4 Marys in the file.
?? ?在上例中,count數組有兩個元素,下標分別為tom和mary,每一個元素的初始值都是0,沒有tom被匹配的時候,count["tom"]就會加一,count["mary"]在匹配mary的時候也同樣如此。END模塊中打印出存儲在數組中的各個元素。
?? ?/> awk '{count[$1]++}; END{for(name in count) printf "%-5s%d\n",name, count[name]}' testfile2
?? ?mary 4
?? ?tom? 2
?? ?alex 1
?? ?bob? 1
?? ?sean 1
?? ?在上例中,awk是以記錄的域作為數組count的下標。
?? ?/> awk '{count[$1]++; if (count[$1] > 1) name[$1]++}; END{print "The duplicates were "; for(i in name) print i}' testfile2
?? ?The duplicates were
?? ?mary
?? ?tom
?? ?在上例中,如count[$1]的元素值大于1的時候,也就是當名字出現多次的時候,一個新的數組name將被初始化,最后打印出那么數組中重復出現的名字下標。
?? ?之前我們介紹的都是如何給數組添加新的元素,并賦予初值,現在我們需要介紹一下如何刪除數組中已經存在的元素。要完成這一功能我們需要使用內置函數delete,見如下命令:
?? ?/> awk '{count[$1]++}; \
?? ??? ?END{for(name in count) {\
?? ???????????? if (count[name] == 1)\
?? ???????????????? delete count[name];\
?? ???????? } \
?? ???????? for (name in count) \
?? ???????????? print name}' testfile2
?? ?mary
?? ?tom
?? ?上例中的主要技巧來自END模塊,先是變量count數組,如果數組中某個元素的值等于1,則刪除該元素,這樣等同于刪除只出現一次的名字。最后用special for循環打印出數組中仍然存在的元素下標名稱。
?? ?最后我們來看一下如何使用命令行參數數組,見如下命令:
?? ?/> awk 'BEGIN {for(i = 0; i < ARGC; i++) printf("argv[%d] is %s.\n",i,ARGV[i]); printf("The number of arguments, ARGC=%d\n",ARGC)}' testfile "Peter Pan" 12
?? ?argv[0] is awk.
?? ?argv[1] is testfile.
?? ?argv[2] is Peter Pan.
?? ?argv[3] is 12.
?? ?The number of arguments, ARGC=4
?? ?從輸出結果可以看出,命令行參數數組ARGV是以0作為起始下標的,命令行的第一個參數為命令本身(awk),這個使用方式和C語句main函數完全一致。
?? ?/> awk 'BEGIN{name=ARGV[2]; print "ARGV[2] is " ARGV[2]}; $1 ~ name{print $0}' testfile2 "bob"?? ?
?? ?ARGV[2] is bob
?? ?bob
?? ?awk: (FILENAME=testfile2 FNR=9) fatal: cannot open file `bob' for reading (No such file or directory)
?? ?先解釋一下以上命令的含義,name變量被賦值為命令行的第三個參數,即bob,之后再在輸入文件中找到匹配該變量值的記錄,并打印出該記錄。
?? ?在輸出的第二行報出了awk的處理錯誤信息,這主要是因為awk將bob視為輸入文件來處理了,然而事實上這個文件并不存在,下面我們需要做進一步的處理來修正這個問題。
?? ?/> awk 'BEGIN{name=ARGV[2]; print "ARGV[2] is " ARGV[2]; delete ARGV[2]}; $1 ~ name{print $0}' testfile2 "bob"?? ?
?? ?ARGV[2] is bob
?? ?bob
?? ?從輸出結果中我們可以看到我們得到了我們想要的結果。需要注意的是delete函數的調用必要要在BEGIN模塊中完成,因為這時awk還沒有開始讀取命令行參數中指定的文件。
????7.? 內建函數:
????字符串函數
?? ?sub(regular expression,substitution string);
?? ?sub(regular expression,substitution string,target string);
?? ?/> awk '{sub("Tom","Tommy"); print}' employees?? #這里使用Tommy替換了Tom。
?? ?Tommy Jones?????? 4424??? 5/12/66???????? 543354
?? ?#當正則表達式Tom在第一個域中第一次被匹配后,他將被字符串"Tommy"替換,如果將sub函數的第三個參數改為$2,將不會有替換發生。
?? ?/> awk '{sub("Tom","Tommy",$1); print}' employees
?? ?Tommy Jones?????? 4424??? 5/12/66???????? 543354
?? ?gsub(regular expression,substitution string);
?? ?gsub(regular expression,substitution string,target string);
?? ?和sub不同的是,如果第一個參數中正則表達式在記錄中出現多次,那么gsub將完成多次替換,而sub只是替換第一次出現的。
?? ?index(string,substring)
?? ?該函數將返回第二個參數在第一個參數中出現的位置,偏移量從1開始。
?? ?/> awk 'BEGIN{print index("hello","el")}'
?? ?2
?? ?length(string)
?? ?該函數返回字符串的長度。
?? ?/> awk 'BEGIN{print length("hello")}'
?? ?5
?? ?substr(string,starting position)
?? ?substr(string,starting position,length of string)
?? ?該函數返回第一個參數的子字符串,其截取起始位置為第二個參數(偏移量為1),截取長度為第三個參數,如果沒有該參數,則從第二個參數指定的位置起,直到string的末尾。
?? ?/>? awk 'BEGIN{name = substr("Hello World",2,3); print name}'
?? ?ell
? ? match(string,regular expression)
?? ?該函數返回在字符串中正則表達式位置的索引,如果找不到指定的正則表達式就返回0.match函數設置內置變量RSTART為字符串中子字符串的開始位置,RLENGTH為到字字符串末尾的字符個數。
?? ?/> awk 'BEGIN{start=match("Good ole CHINA", /[A-Z]+$/); print start}'
?? ?10
?? ?上例中的正則表達式[A-Z]+$表示在字符串的末尾搜索連續的大寫字母。在字符串"Good ole CHINA"的第10個位置找到字符串"CHINA"。
? ? /> awk 'BEGIN{start=match("Good ole CHINA", /[A-Z]+$/); print RSTART, RLENGTH}'
?? ?10 5
?? ?RSTART表示匹配時的起始索引,RLENGTH表示匹配的長度。
?? ?/> awk 'BEGIN{string="Good ole CHINA";start=match(string, /[A-Z]+$/); print substr(string,RSTART, RLENGTH)}'
?? ?CHINA
?? ?這里將match、RSTART、RLENGTH和substr巧妙的結合起來了。
?? ?toupper(string)
?? ?tolower(string)
?? ?以上兩個函數分別返回參數字符串的大寫和小寫的形式。
?? ?/> awk 'BEGIN {print toupper("hello"); print tolower("WORLD")}'
?? ?HELLO
?? ?world
?? ?split(string,array,field seperator)
?? ?split(string,array)
?? ?該函數使用作為第三個參數的域分隔符把字符串分隔為一個數組。如果第三個參數沒有提供,則使用當前默認的FS值。
?? ?/> awk 'BEGIN{split("11/20/2011",date,"/"); print date[2]}'
?? ?20
?? ?variable = sprintf("string with format specifiers ",expr1,expr2,...)
?? ?該函數和printf的差別等同于C語言中printf和sprintf的差別。前者將格式化后的結果輸出到輸出流,而后者輸出到函數的返回值中。
?? ?/> awk 'BEGIN{line = sprintf("%-15s %6.2f ", "hello",4.2); print line}'
?? ?hello???????????? 4.20
?? ?時間函數:
?? ?systime()
?? ?該函數返回當前時間距離1970年1月1日之間相差的秒數。
?? ?/> awk 'BEGIN{print systime()}'
?? ?1321369554
?? ?strftime()
?? ?時間格式化函數,其格式化規則等同于C語言中的strftime函數提供的規則,見以下列表:
| 數據格式 | 含義 |
| %a | Abbreviated weekday name |
| %A | Full weekday name |
| %b | Abbreviated month name |
| %B | Full month name |
| %c | Date and time representation appropriate for locale |
| %d | Day of month as decimal number (01 – 31) |
| %H | Hour in 24-hour format (00 – 23) |
| %I | Hour in 12-hour format (01 – 12) |
| %j | Day of year as decimal number (001 – 366) |
| %m | Month as decimal number (01 – 12) |
| %M | Minute as decimal number (00 – 59) |
| %p | Current locale's A.M./P.M. indicator for 12-hour clock |
| %S | Second as decimal number (00 – 59) |
| %U | Week of year as decimal number, with Sunday as first day of week (00 – 53) |
| %w | Weekday as decimal number (0 – 6; Sunday is 0) |
| %W | Week of year as decimal number, with Monday as first day of week (00 – 53) |
| %x | Date representation for current locale |
| %X | Time representation for current locale |
| %y | Year without century, as decimal number (00 – 99) |
| %Y | Year with century, as decimal number |
??? /> awk 'BEGIN{ print strftime("%D",systime())}'
?? ?11/15/11
?? ?/> awk 'BEGIN{ now = strftime("%T"); print now}'
?? ?23:17:29
?? ?內置數學函數:
| 名稱 | 返回值 |
| atan2(x,y) | y,x范圍內的余切 |
| cos(x) | 余弦函數 |
| exp(x) | 求冪 |
| int(x) | 取整 |
| log(x) | 自然對數 |
| sin(x) | 正弦函數 |
| sqrt(x) | 平方根 |
??? /> awk 'BEGIN{print 31/3}'
?? ?10.3333
?? ?/> awk 'BEGIN{print int(31/3)}'
?? ?10
?? ?自定義函數:
?? ?自定義函數可以放在awk腳本的任何可以放置模板和動作的地方。
?? ?function name(parameter1,parameter2,...) {
?? ??? ?statements
?? ??? ?return expression
?? ?}
?? ?給函數中本地變量傳遞值。只使用變量的拷貝。數組通過地址或者指針傳遞,所以可以在函數內部直接改變數組元素的值。函數內部使用的任何沒有作為參數傳遞的變量都被看做是全局變量,也就是這些變量對于整個程序都是可見的。如果變量在函數中發生了變化,那么就是在整個程序中發生了改變。唯一向函數提供本地變量的辦法就是把他們放在參數列表中,這些參數通常被放在列表的最后。如果函數調用沒有提供正式的參數,那么參數就初始化為空。return語句通常就返回程序控制并向調用者返回一個值。
?? ?/> cat grades
?? ?20 10
?? ?30 20
?? ?40 30
?? ?/> cat add.sc
?? ?function add(first,second) {
?? ???????? return first + second
?? ?}
?? ?{ print add($1,$2) }
?? ?/> awk -f add.sc grades
?? ?30
?? ?50
?? ?70
總結
以上是生活随笔為你收集整理的Linux Shell常用技巧(五)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux Shell常用技巧(四)
- 下一篇: Linux Shell常用技巧(六)