(9)awk getline用法詳解

2022-06-12 17:09:15 字數 4802 閱讀 5123

除了可以從標準輸入或非選項型引數所指定的檔案中讀取資料,還可以使用getline從其它各種渠道獲取需要處理的資料,它的用法有很多種。

getline的返回值:

為了健壯性,getline時強烈建議進行判斷。例如:

上面的getline的括號盡量加上,因為getline < 0表示的是輸入重定向,而不是和數值0進行小於號的比較。

getline無引數時,表示從當前正在處理的檔案中立即讀取下一條記錄儲存到$0中,並進行字段分割,然後繼續執行後續**邏輯。

此時的getline會設定nf、rt、nr、fnr、$0和$n。

next也可以讀取下一行。

它們之間的區別用偽**描述,類似於:

# next

exec

9<>filename

while read -u 9 line;do

...code...

continue # next

...code... # 這部分**在本輪迴圈當中不再執行

done

# getline

while read -u 9 line;do

...code...

read -u 9

line # getline

...code...

done

例如,匹配到某行之後,再讀一行就退出:

[root@docker-01 ~]# awk

'/^1/

'a.txt

1 bob male 28 [email protected] 18023394012

2 alice female 24 [email protected] 18084925203

為了更健壯,應當對getline的返回值進行判斷。

[root@docker-01 ~]# awk

'/^1/;print}

'a.txt

1 bob male 28 [email protected] 18023394012

2 alice female 24 [email protected] 18084925203

10 bruce female 27 [email protected] 13942943905

[root@docker-01 ~]# awk

'/^1/;print}

'a.txt

1 bob male 28 [email protected] 18023394012

沒有引數的getline是讀取下一條記錄之後將記錄儲存到$0中,並對該記錄進行欄位的分割。

乙個引數的getline是將讀取的記錄儲存到指定的變數當中,並且不會對其進行分割。

getline var
此時的getline只會設定rt、nr、fnr變數和指定的變數var。因此$0和$n以及nf保持不變。

filename需使用雙引號包圍表示檔名字串,否則會當作變數解析getline < "c.txt"。此外,如果路徑是使用變數構建的,則應該使用括號包圍路徑部分。例如getline < dir "/" filename中使用了兩個變數構建路徑,這會產生歧義,應當寫成getline 。

注意,每次從filename讀取之後都會做好位置偏移標記,下次再從該檔案讀取時將根據這個位置標記繼續向後讀取。

例如,每次行首以1開頭時就讀取c.txt檔案的所有行。

awk '

/^1/;

close("c.txt")

}' a.txt

上面的close("c.txt")表示在while(getline)讀取完檔案之後關掉,以便後面再次讀取,如果不關掉,則檔案偏移指標將一直在檔案結尾處,使得下次讀取時直接遇到eof。

cmd | getline var:從shell命令cmd的輸出結果中讀取資料儲存到var中

如果要再次執行cmd並讀取其輸出資料,則需要close關閉該命令。例如close("seq 1 5"),參見下面的示例。

例如:每次遇到以1開頭的行都輸出seq命令產生的1 2 3 4 5

awk '/^1/;close("seq 1 5")}' a.txt

再例如,呼叫shell的date命令生成時間,然後儲存到awk變數cur_date中:

awk '

/^1/' a.txt

可以將cmd儲存成乙個字串變數。

awk '

begin

/^1/' a.txt

更為複雜一點的,cmd中可以包含shell的其它特殊字元,例如管道、重定向符號等:

awk '

/^1/y 2>/dev/null"|getline) > 0)

close("seq 1 5 | xargs -i echo x{}y 2>/dev/null")

}' a.txt

awk雖然強大,但是有些資料仍然不方便處理,這時可將資料交給shell命令去幫助處理,然後再從shell命令的執行結果中取回處理後的資料繼續awk處理。

awk通過|&符號來支援coproc。

awk_print[f] "something" |& shell_cmd

shell_cmd |& getline [var]

這表示awk通過print輸出的資料將傳遞給shell的命令shell_cmd去執行,然後awk再從shell_cmd的執行結果中取回shell_cmd產生的資料。

例如,不想使用awk的substr()來取子串,而是使用sed命令來替換。

awk '

begin

nr>1' a.txt

對於awk_print |& cmd; cmd |& getline的使用,須注意的是:

對於那些要求讀完所有資料再執行的命令,例如sort命令,它們有可能需要等待資料已經完成後(遇到eof標記)才開始執行任務,對於這些命令,可以多次向coprocess中寫入資料,最後close(cmd,"to")讓coprocess執行起來。

例如,對age欄位(即$4)使用sort命令按數值大小進行排序:

awk '

begin

# 將所有行都寫進管道

nr>1

endclose(cmd);

} ' a.txt

close(filename)

close(cmd,[from | to]) # to引數只用於coprocess的第乙個階段

如果close()關閉的物件不存在,awk不會報錯,僅僅只是讓其返回乙個負數返回值。

close()有兩個基本作用:

awk中任何檔案都只會在第一次使用時開啟,之後都不會再重新開啟。只有關閉之後,再使用才會重新開啟。

例如乙個需求是只要在a.txt中匹配到1開頭的行就輸出另乙個檔案x.log的所有內容,那麼在第一次輸出x.log檔案內容之後,檔案偏移指標將在x.log檔案的結尾處,如果不關閉該檔案,則後續所有讀取x.log的檔案操作都從結尾處繼續讀取,但是顯然總是得到eof異常,所以getline返回值為0,而且也讀取不到任何資料。所以,必須關閉它才能在下次匹配成功時再次從頭讀取該檔案。

awk '

/^1/

close("x.log")

}' a.txt

在處理coprocess的時候,close()可以指定第二個引數"from"或"to",它們都針對於coproc而言,from時表示關閉coproc |& getline的管道,使用to時,表示關閉print something |& coproc的管道。

awk '

begin

nr>1' a.txt

上面的第乙個close是必須的,否則sed會一直阻塞。因為sed一直認為還有資料可讀,只有關閉管道傳送乙個eof,sed才會開始處理。

TCP IP詳解筆記 9

tftp簡單文字傳輸協議和bootp引導程式協議 tftp協議 同時為了允許多個客戶併發的進行系統引導,tftp通過為每個客戶分配乙個埠號來實現併發。tftp協議沒有提供安全性。bootp引導程式協議 在arp協議時說過可以通過rarp來得到自己的ip,但這只能得到ip位址,且該子網下必須存在rar...

const用法詳解

物件導向是c 的重要特性.但是c 在c的基礎上新增加的幾點優化也是很耀眼的 就const直接可以取代c中的 define 以下幾點很重要,學不好後果也也很嚴重 1.const常量,如const int max 100 優點 const常量有資料型別,而巨集常量沒有資料型別。編譯器可以對前者進行型別安...

const 用法詳解

物件導向是c 的重要特性.但是c 在c的基礎上新增加的幾點優化也是很耀眼的 就const直接可以取代c中的 define 以下幾點很重要,學不好後果也也很嚴重 1.const常量,如const int max 100 優點 const常量有資料型別,而巨集常量沒有資料型別。編譯器可以對前者進行型別安...