1. 程式人生 > >awk純乾貨

awk純乾貨

AWK的驚人表現:

Awk設計的目的:簡化一般文字處理的工作。

屬於POSIX的一部分。

 

AWK命令列:

Awk的呼叫可以定義變數、提供程式並且指定輸入檔案:

 

  • Awk [ -F fs ]  [ -v var=value ... ] 'program' [ -- ] \
  • [ var=value ... ] [ file(s) ]
  • Awk [ -F fs ]  [ -v var=value ... ] -f program'file [ -- ] \
  • [ var=value ... ] [ file(s) ] 

 

短程式通常是直接在命令列上提供,而比較長的程式,則委託-f選項指定,遇到需連線被指名的程式檔案以得到完整的程式時,則可重複使用此選項,這是包含共享awk程式碼的程式庫存之方便用法。選項需置於檔名以及一般var=value賦值的前面。

-- 是特殊選項:指出awk本身已沒有更進一步的命令列選項,任何接下來的選項都可被你的程式使用。

 

-f選項是用來重新定義預設欄位分隔字元,且一般慣例將它作為第一個命令列選項,緊接在-F選項後的fs引數是一個正則表示式,或是被提供作為下一個引數。欄位分隔字元也可設定使用內建變數FS所指定的:

 

初始化的-v

選項必須放在命令列上直接給定的任何程式之前,它們會在程式啟動之前以及處理任何檔案之前生效,在一命令列程式之後的-v選項會被解釋為一個檔名可(能是不存在的)

 

在命令列上其它地方的初始化會在處理引數時完成,並且會帶上檔名。例如:

Awk '{ ... }' Pass=1 *.tex Pass=2 *.tex

處理檔案的列表兩次,第一次是Pass設為1,第二次將它設為2.

注:使用字串值進行初始化無須用引號框起來,除非shell要求這樣的引用,以保護牸字元或空白。支援正則。

注:特殊檔名-(連字號)表示標準輸入。/dev/stdin為標準輸入,/dev/stderr標準錯誤輸出,/dev/stdout

標準輸出。

 

Awk程式模型:

 

Awk把輸入流看作一連串記錄的集合,每條記錄都可進一步細分為欄位,通常,一行一條記錄,而欄位則由一個或多個非空白字元的單片語成。然而,是什麼構成一條記錄和一個欄位,完全是由程式設計師控制,且它們的定義,甚至可以在處理期間更改。

一個awk程式是一對以模式(pattern)與大括號框起來的操作(action)組合而成的。

 

輸入會自動地由一個輸入檔案切換到下一個,且awk本身通常會處理每個輸入檔案的開啟、讀取和關閉,以允許使用者程式專心致力於記錄的處理。雖然模式多半是資料或字串表示式,不過awk以保留字BEGINEND提供兩種特殊模式。

 

程式元素:awk處理數字與字串資料,提供了標量(scalar)與陣列(array)兩種變數以儲存資料、數字與字串表示式。還提供了一些語句型別以處理資料:賦值、註釋、條件、函式、輸入、迴圈及輸出。

 

#號註釋單行,單條語句多行可用反斜槓。

 

字串的比較,用的是傳統的關係運算符。返回1為真,0為假。Awk並無特殊的字串接續運算子。兩個連續字串,會自動地連線在一起。

 

支援正則表示式,有兩個運算子:~(匹配)與!~(不匹配)

 

正則表示式常量可以用引號或斜槓加以定介:"ABC" ~ /^[A-Z]+$/ 等同於"ABC" ~ "^[A-Z]+$" ,如果在引號字串里正好需要有字面意義的引號,則應以反斜槓("...\"...")保護。

 

Awk處理字串轉資料的函式,s = "123" 接著n = 0  + s ,便將資料123賦值給n了。(並不適用)

 

Awk的數值運算子[


Awk可用括號以控制計算順序。

一、複合式,像/=這樣,以左邊運算數作為右這的第一個去處數。N /=3 便是n=n/3

二、賦值的結果用來作為另一個表示式的部分表示式:(賦值運算子為右結合性)

 

Awk裡一般常用到的內建標量變數


命令列引數

Awk對於命令列的自動化處理,awk通過內變數ARGC(引數計數)ARGV(引數向量,或引數值),讓命令列引數可用。

 

awk程式化模式中,通過輸入檔案隱含迴圈的每一次迭代,會處理單一記錄(record),通常是一行文字,記錄可進一步再侵害為更小的字串,叫做欄位(field)

 

FS的預設值為單一空格,它接受特殊的解釋方式 。一個或多個空白字元(空格與製表字元)以及行的開頭與結尾的空白,都將被忽略。因此a b a        b相同。

----------------------------

[[email protected] 8csjb]# cat awkfs

a b c d

a        b        c        d        e        f

[[email protected] 8csjb]# awk -F" " '{print $1,$2,$3,$4,$5,$6}' awkfs

a b c d  

a b c d e f

--------------------------------------------------

匹配單個空格設定FS  = "[ ]"

 

欄位可以特殊名稱$1\$2...$NFawk程式使用。欄位引用無須是固定的,有必須的話,它們還可以轉換(通過截斷)為整數值:假定k3,則值$k\$(1+2)$(27/9)、以及$3、都引用到第三個欄位。特殊欄位名稱$0引用到當前的記錄,初始值是從輸入流中讀取,且記錄分隔字元不是記錄的一部分。引用到0NF範圍以上的欄位編號是不會有錯。

 

模式與操作構成awk程式的核心,awk的非傳統資料驅動程式模式,使得它更吸引使用者使用,也成就了許多awk程式的簡潔形式。

 

模式由字串與或數值表示式構建而成:一昊它們計算出當前輸入記錄的值為非零(真),則實行結合性的操作。如果模式是正則表示式,則意指此表示式會被來與整個輸入記錄進行匹配。

 

操作段落是可選地接在一個模式之後,也就是操作所在之處:它標明瞭如何處理該記錄。

 

常見用法:一個print語句裡包含了以逗號隔開的零或多個表示式,每個表示式會被計算,有必要時會轉換為一個字串,且以輸出欄位分隔字元OFS的值將輸出分隔後傳送到標準輸出,接在最後專案之後的是輸出記錄分隔字元ORS的值。

-------------------------------------------------------------------------------------------

[[email protected] ~]# echo '1 2 3 4 5 a' |awk '{ OFS ="abc"; print $1,$2,$3,$4,$5,$6}'

1abc2abc3abc4abc5abca

[[email protected] ~]# echo '1 2 3 4 5 a' |awk '{ OFS ="\n"; print $1,$2,$3,$4,$5,$6}'

1

2

3

4

5

a

[[email protected] ~]# echo '1 2 3 4 5 a' |awk '{ OFS =" "; print $1,$2,$3,$4,$5,$6}'

1 2 3 4 5 a

------------------------------------------------------------------------------------------------------

改變輸出欄位分隔字元而沒有指定任何欄位,不會改變$0;,如果我們更改輸出欄位分隔字元,並指定至少一個欄位(即強制以新的欄位分隔字元重新組合記錄)結果為

[[email protected] ~]# echo '1 2 3 4 5 a' |awk '{ OFS ="\n";  print $0}'

1 2 3 4 5 a

[[email protected] ~]# echo '1 2 3 4 5 a' |awk '{ OFS ="\n"; $1=$1; print $0}'

1

2

3

4

5

A

----------------------------------------------------------------------

 

如果程式為空,則awk不會讀取任何輸入並立即退出,所以我們可以匹配cat

除開NUL字元問題,awk可以輕鬆取代cat

 

大量例項:

要將原始數值及它們的對數列印為單欄的資料檔案,可使用:

Awk '{ print $1, log($1) }' file(s)

列印文字檔案5%行左右的隨機樣本。使用虛擬承受機產行函式。

Awk 'rand() <0.05' file(s)

在以空白分隔欄位的表格中,報告第n欄的和:

Awk -v COLUMN=n '{ sum += $COLUMN} END { print sum }' file(s)

------------------------------------------------------------------------------------

[[email protected] 8csjb]# echo "2" |awk -v COLUMN=n '{ sum += $COLUMN} END { print sum }'

2         #字元視為0

[[email protected] 8csjb]# echo "2" |awk -v COLUMN=n '{ sum += $COLUMN} END { print sum/2 }'

1        #算術運算子

[[email protected] 8csjb]# awk '/print/' awk        #等同於grep 'print' awk

print "ARGC =", ARGC

print "ARGV[" k "] = [" ARGV[k] "]"

查詢100-150

[[email protected] 8csjb]# awk '(1 <= FNR) && (FNR <=15) && /print/ {print FILENAME ":" FNR ":" $0 }' awk

awk:2:        print "ARGC =", ARGC

awk:4:        print "ARGV[" k "] = [" ARGV[k] "]"

sed如下:

[[email protected] 8csjb]# sed -n  1,15p -s awk |egrep 'print'

print "ARGC =", ARGC

print "ARGV[" k "] = [" ARGV[k] "]"

[[email protected] 8csjb]# awk 'BEGIN { FS = "print"; OFS = "&" } { $1=$1;print}' awk

BEGIN{

& "ARGC =", ARGC

for (k=0; k<ARGC; k++)

& "ARGV[" k "] = [" ARGV[k] "]"

}

刪除已排序流裡的重複行:

Sort file(s) |uniq

Sort file(s) | awk 'Last !=$0 { print } { Lst =$0 }'

將回車字元/換行字元的行終結,一致轉換為以換行字元作為行終結。

Sed -e 's/\r$//' file(s)

Sed -e 's/^M$//' file(s)        #^M ctrl+M

Mawk ''BEGIN { RS = "\r\n" } {print }' file(s)  

 

要將單空格的文字行,轉換為雙空格的行。

-------------------------------------------------------------------------------------------------------

[[email protected] 8csjb]# sed -e 's/$/\n/' awk

BEGIN{

 

print "ARGC =", ARGC

 

for (k=0; k<ARGC; k++)

 

print "ARGV[" k "] = [" ARGV[k] "]"

 

}

[[email protected] 8csjb]# awk 'BEGIN { ORS = "\n\n"} {print}' awk         #記錄分隔符ORS

[[email protected] 8csjb]# awk 'BEGIN { ORS = "\n\n"} 1'  awk

[[email protected] 8csjb]# awk '{ print $0 "\n"}'   awk

[[email protected] 8csjb]# awk '{ print; print "" }'   awk

將雙空格行轉換為單空格一樣是很容易的:

[[email protected] 8csjb]# awk '{ print; print "" }'   awk|awk 'BEGIN {RS ="\n *\n" } {print}'

BEGIN{

print "ARGC =", ARGC

for (k=0; k<ARGC; k++)

print "ARGV[" k "] = [" ARGV[k] "]"

}

尋找超過限制長度72個字元的行

egrep -n '^.{73,}' file(s)

[[email protected] 8csjb]# awk 'length($0) >3 {print FILENAME ":" FNR ":" $0 }' awk

awk:1:BEGIN{

awk:2:        print "ARGC =", ARGC

awk:3:        for (k=0; k<ARGC; k++)

awk:4:        print "ARGV[" k "] = [" ARGV[k] "]"

 

查詢html標題內容

Awk -v ORS=' ' -v RS='( \n)' '/<title *>/, /<\/tiltle *>/' file(s) | sed -e '[email protected]</title *> *@&\[email protected]'

煮酒品茶:可以更新批量下載網頁那東西了,取標題頁。@/沒區別。特別環境特別使用。

 

語句:程式語言必須支援連續性的、條件式的及重複的執行。

連續執行如:a=1;b=2;c=3

條件式執行:

If (expression)

Statement1

Else

Statemnt2

 

重複執行whiledo) (forfor)

 

注意:因為浮點算術通常不精確,所以避免在for語句表示式裡,計算非整數的值。

 

其它的流程控制語句

只針對此記錄略過更進一步的模式檢查。

使用Next語句。

針對當前輸入檔案略過更進一步的模式檢查。

Gawk與近期的nawk都提供nextfile語句,它會使得當前輸入檔案立即關閉且模式的匹配會從命令列上下一個檔案裡的記錄重新開始。

 

使用者控制的輸入

Awk直接處理命令列上標明的輸入檔案,意指絕大多數的awk程式都不必自己開啟與處理檔案。它也可以通過awkgetline語句來做這件事情。

 


awk支援重定向。


 

基礎數值函式



來源: <http://bbs.magedu.com/thread-40-1-1.html>