linux的gawk命令
目錄
1.awk 簡介
2.awk 概述
3. 工作原理
4.gawk程序的可用選項
5.基礎使用示例
5.1 使用數據字段變量:
5.2 指定分隔符
5.3 在程序腳本中使用多個命令
5.4 從文件中讀取程序
5.5 在處理數據前后運行腳本
6 進階使用
6.1內置變量
1.字段和記錄分隔符變量:
2.數據變量
6.2自定義變量
1. 在腳本中給變量賦值
2.在命令行上給變量賦值
6.3 處理數組
1.定義數組變量
2.遍歷數組變量
3.刪除數組變量
6.4 使用模式
1.正則表達式
2.匹配操作符
3.數學表達式
6.5 結構化命令
1. if 語句
2.while 語句
3.for語句
6.6 格式化打印
6.7 內建函數
1.數學函數
2.字符串函數
3. 時間函數
4.自定義函數
7.實例
?
1.awk 簡介
awk 以記錄和字段的方式來查看文本文件
和其他編程語言一樣, awk 包含變量、條件和循環
awk 能夠進行運算和字符串操作
awk 能夠生成格式化的報表數據
2.awk 概述
awk 程序 awk 命令、括在括號(或寫在文件)中的程序指令以及輸入文件的文件名幾個部分組成。如果沒有輸入文件,輸入則來自于標準輸入。
awk 指令由模式、操作或者模式與操作的組合組成。模式是由某種類型的表達式組成的語句。如果某個表達式中沒有出現關鍵在 if ,但實際在計算時卻暗含 if 這個詞,那么這個表達式就是模式。操作由括在大括號中的一條或多條語句組成,語句之間用分號或者換行符隔開。模式不能括在大括號中,模式由包括在兩個正斜杠之間的正則表達式、一個或多個 awk 操作符組成的表達式組成。
格式:
awk '/search pattern1/ {Actions}
/search pattern2/ {Actions}' file
3. 工作原理
awk 使用一行作為輸入(通過文件或者管道),并將這一行賦給內部變量 $0
行被空格分解為字段(單詞),每一個字段存儲在已編號的變量中,從 $1 開始。( awk 的內部變量 FS 用來確定字段的分隔符。初始時,為空格,包含制表符和空格符)
對于一行,按照給定的正則表達式的順序進行匹配,如果匹配則執行對應的 Action ,如果沒有匹配上則不執行任何動作 , Search Pattern 和 Action 是可選的,但是必須提供其中一個 。如果 Search Pattern 未提供,則對所有的輸入行執行 Action 操作。如果 Action 未提供,則默認打印出該行的數據 。 {} 這種 Action 不做任何事情,和未提供的 Action 的工作方式不一樣
打印字段,用 print 、 printf 、 sprintf ,格式: { print $1, $3 } 內部變量 output field separator ( OFS ),默認為空格, $n 之間的逗號被 OFS 中的字符替換。
輸出之后,從文件中另取一行,并將其復制到 $0 中,覆蓋原來的內容。重復進行……
4.gawk程序的可用選項
5.基礎使用示例
5.1 使用數據字段變量:
- ?$0 代表整個文本行;
- ?$1 代表文本行中的第1個數據字段;
- ?$2 代表文本行中的第2個數據字段;
- ?$n 代表文本行中的第n個數據字段。
該程序用 $1 字段變量來僅顯示每行文本的第1個數據字段。
5.2 指定分隔符
如果你要讀取采用了其他字段分隔符的文件,可以用 -F 選項指定。
gawk -F: '{print $1}' /etc/passwd這個簡短的程序顯示了系統中密碼文件的第1個數據字段。由于/etc/passwd文件用冒號來分隔數字字段,因而如果要劃分開每個數據元素,則必須在 gawk 選項中將冒號指定為字段分隔符
5.3 在程序腳本中使用多個命令
如果一種編程語言只能執行一條命令,那么它不會有太大用處。gawk編程語言允許你將多條命令組合成一個正常的程序。要在命令行上的程序腳本中使用多條命令,只要在命令之間放個分號即可。
第一條命令會給字段變量 $4 賦值。第二條命令會打印整個數據字段。注意, gawk程序在輸出中已經將原文本中的第四個數據字段替換成了新值。
5.4 從文件中讀取程序
跟sed編輯器一樣,gawk編輯器允許將程序存儲到文件中,然后再在命令行中引用
script2.gawk程序腳本會再次使用 print 命令打印/etc/passwd文件的主目錄數據字段(字段變量 $6 ),以及 userid 數據字段(字段變量 $1 )。
可以在程序文件中指定多條命令。要這么做的話,只要一條命令放一行即可,不需要用分號。
5.5 在處理數據前后運行腳本
gawk還允許指定程序腳本何時運行。默認情況下,gawk會從輸入中讀取一行文本,然后針對該行的數據執行程序腳本。有時可能需要在處理數據前運行腳本,比如為報告創建標題。 BEGIN關鍵字就是用來做這個的。它會強制gawk在讀取數據前執行 BEGIN 關鍵字后指定的程序腳本。
在gawk執行了BEGIN腳本后,它會用第二段腳本來處理文件數據。這么做時要小心,兩段腳本仍然被認為是 gawk 命令行中的一個文本字符串。你需要相應地加上單引號。
與 BEGIN 關鍵字類似, END 關鍵字允許你指定一個程序腳本,gawk會在讀完數據后執行它。
6 進階使用
6.1內置變量
1.字段和記錄分隔符變量:
變量 FS 和 OFS 定義了gawk如何處理數據流中的數據字段。你已經知道了如何使用變量 FS 來定義記錄中的字段分隔符。變量 OFS 具備相同的功能,只不過是用在 print 命令的輸出上。默認情況下,gawk將 OFS 設成一個空格,所以如果你用命令:
print $1,$2,$3會看到如下輸出:
field1 field2 field3print 命令會自動將 OFS 變量的值放置在輸出中的每個字段間。通過設置 OFS 變量,可以在輸出中使用任意字符串來分隔字段。
FIELDWIDTHS 變量允許你不依靠字段分隔符來讀取記錄。在一些應用程序中,數據并沒有使用字段分隔符,而是被放置在了記錄中的特定列。這種情況下,必須設定 FIELDWIDTHS 變量來匹配數據在記錄中的位置。一旦設置了 FIELDWIDTH 變量,gawk就會忽略 FS 變量,并根據提供的字段寬度來計算字段。下面是個采用字段寬度而非字段分隔符的例子。
FIELDWIDTHS 變量定義了四個字段,gawk依此來解析數據記錄。每個記錄中的數字串會根據已定義好的字段長度來分割
警告 :一定要記住,一旦設定了 FIELDWIDTHS 變量的值,就不能再改變了。這種方法并不適用于變長的字段。
變量 RS 和 ORS 定義了gawk程序如何處理數據流中的字段。默認情況下,gawk將 RS 和 ORS 設為換行符。默認的 RS 值表明,輸入數據流中的每行新文本就是一條新紀錄。有時,你會在數據流中碰到占據多行的字段。典型的例子是包含地址和電話號碼的數據,其
中地址和電話號碼各占一行。
如果你用默認的 FS 和 RS 變量值來讀取這組數據,gawk就會把每行作為一條單獨的記錄來讀取,并將記錄中的空格當作字段分隔符。這可不是你希望看到的。要解決這個問題,只需把 FS 變量設置成換行符。這就表明數據流中的每行都是一個單獨的字段,每行上的所有數據都屬于同一個字段。但現在令你頭疼的是無從判斷一個新的數據行從何開始。
?????? 對于這一問題,可以把 RS 變量設置成空字符串,然后在數據記錄間留一個空白行。gawk會把每個空白行當作一個記錄分隔符。
2.數據變量
除了字段和記錄分隔符變量外,gawk還提供了其他一些內建變量來幫助你了解數據發生了什么變化,并提取shell環境的信息
你應該能從上面的列表中認出一些shell腳本編程中的變量。 ARGC 和 ARGV 變量允許從shell中獲得命令行參數的總數以及它們的值。但這可能有點麻煩,因為gawk并不會將程序腳本當成命令行參數的一部分。
ARGC 變量表明命令行上有兩個參數。這包括 gawk 命令和 data1 參數(記住,程序腳本并不算參數)。 ARGV 數組從索引 0 開始,代表的是命令。第一個數組值是 gawk 命令后的第一個命令行參數。
說明 跟shell變量不同,在腳本中引用gawk變量時,變量名前不加美元符。
ENVIRON["HOME"] 變量從shell中提取了 HOME 環境變量的值。類似地, ENVIRON["PATH"] 提取了 PATH 環境變量的值??梢杂眠@種方法來從shell中提取任何環境變量的值,以供gawk程序使用。
?????? 當要在gawk程序中跟蹤數據字段和記錄時,變量 FNR 、 NF 和 NR 用起來就非常方便。有時你并不知道記錄中到底有多少個數據字段。 NF 變量可以讓你在不知道具體位置的情況下指定記錄中的最后一個數據字段。
NF: The variable NF is set to the total number of fields in the input record.
?????? NR:The total number of input records seen so far.
????? NF 變量含有數據文件中最后一個數據字段的數字值??梢栽谒懊婕觽€美元符將其用作字段變量。
????? FNR 和 NR 變量雖然類似,但又略有不同。 FNR 變量含有當前數據文件中已處理過的記錄數,NR 變量則含有已處理過的記錄總數。讓我們看幾個例子來了解一下這個差別
在這個例子中,gawk程序的命令行定義了兩個輸入文件(兩次指定的是同樣的輸入文件)。這個腳本會打印第一個數據字段的值和 FNR 變量的當前值。注意,當gawk程序處理第二個數據文件時, FNR 值被設回了 1 。
FNR 變量的值在 gawk 處理第二個數據文件時被重置了,而 NR 變量則在處理第二個數據文件時繼續計數。結果就是:如果只使用一個數據文件作為輸入, FNR 和 NR 的值是相同的;如果使用多個數據文件作為輸入, FNR 的值會在處理每個數據文件時被重置,而 NR 的值則會繼續計數直到處理完所有的數據文件。
6.2自定義變量
跟其他典型的編程語言一樣,gawk允許你定義自己的變量在程序代碼中使用。gawk自定義變量名可以是任意數目的字母、數字和下劃線,但不能以數字開頭。重要的是,要記住 gawk 變量名區分大小寫
1. 在腳本中給變量賦值
在gawk程序中給變量賦值跟在shell腳本中賦值類似,都用賦值語句
print 語句的輸出是 testing 變量的當前值。跟shell腳本變量一樣, gawk 變量可以保存數值或文本值
在這個例子中, testing 變量的值從文本值變成了數值.賦值語句還可以包含數學算式來處理數字值:
2.在命令行上給變量賦值
也可以用 gawk 命令行來給程序中的變量賦值。這允許你在正常的代碼之外賦值,即時改變變量的值。下面的例子使用命令行變量來顯示文件中特定數據字段
這個特性可以讓你在不改變腳本代碼的情況下就能夠改變腳本的行為。第一個例子顯示了文件的第二個數據字段,第二個例子顯示了第三個數據字段,只要在命令行上設置 n 變量的值就行。使用命令行參數來定義變量值會有一個問題。在你設置了變量后,這個值在代碼的 BEGIN 部分不可用。
可以用 -v 命令行參數來解決這個問題。它允許你在 BEGIN 代碼之前設定變量。在命令行上,-v 命令行參數必須放在腳本代碼之前。
6.3 處理數組
1.定義數組變量
可以用標準賦值語句來定義數組變量。數組變量賦值的格式如下:
var[index] = element其中 var 是變量名, index 是關聯數組的索引值, element 是數據元素值。下面是一些gawk中數組變量的例子。在引用數組變量時,必須包含索引值來提取相應的數據元素值
在引用數組變量時,會得到數據元素的值。數據元素值是數字值時也一樣:
2.遍歷數組變量
關聯數組變量的問題在于你可能無法知曉索引值是什么。跟使用連續數字作為索引值的數字數組不同,關聯數組的索引可以是任何東西。如果要在gawk中遍歷一個關聯數組,可以用 for 語句的一種特殊形式。
for (var in array) { statements }這個 for 語句會在每次循環時將關聯數組 array 的下一個索引值賦給變量 var ,然后執行一遍 statements 。重要的是記住這個變量中存儲的是索引值而不是數組元素值??梢詫⑦@個變量用作數組的索引,輕松地取出數據元素值。
注意:索引值不會按任何特定順序返回,但它們都能夠指向對應的數據元素值。明白這點很重要,因為你不能指望著返回的值都是有固定的順序,只能保證索引值和數據值是對應的
3.刪除數組變量
從關聯數組中刪除數組索引要用一個特殊的命令
delete array[index]刪除命令會從數組中刪除關聯索引值和相關的數據元素值
6.4 使用模式
1.正則表達式
在使用正則表達式時,正則表達式必須出現在它要控制的程序腳本的左花括號前。
正則表達式 /11/ 匹配了數據字段中含有字符串 11 的記錄。gawk程序會用正則表達式對記錄中所有的數據字段進行匹配,包括字段分隔符。
2.匹配操作符
匹配操作符(matching operator)允許將正則表達式限定在記錄中的特定數據字段。匹配操作符是波浪線( ~ )。可以指定匹配操作符、數據字段變量以及要匹配的正則表達式.
$1 ~ /^data/$1 變量代表記錄中的第一個數據字段。這個表達式會過濾出第一個字段以文本 data 開頭的所有記錄。下面是在gawk程序腳本中使用匹配操作符的例子。
匹配操作符會用正則表達式 /^data2/ 來比較第二個數據字段,該正則表達式指明字符串要以文本 data2 開頭。并使用$0打印整行內容.這可是件強大的工具,gawk程序腳本中經常用它在數據文件中搜索特定的數據元素
這個例子會在第一個數據字段中查找文本 root。如果在記錄中找到了這個模式,它會打印該記錄的第一個和最后一個數據字段值。
你也可以用 ! 符號來排除正則表達式的匹配
$1 !~ /expression/如果記錄中沒有找到匹配正則表達式的文本,程序腳本就會作用到記錄數據
在這個例子中,gawk程序腳本會打印/etc/passwd文件中與用戶ID root不匹配的用戶ID和登錄shell。
3.數學表達式
除了正則表達式,你也可以在匹配模式中用數學表達式。這個功能在匹配數據字段中的數字值時非常方便。舉個例子,如果你想顯示所有屬于root用戶組(組ID為 0 )的系統用戶,可以用這個腳本。
gawk -F: '$4 == 0{print $1}' /etc/passwd這段腳本會查看第四個數據字段含有值 0 的記錄。在這個Linux系統中,有五個用戶賬戶屬于root用戶組。
可以使用任何常見的數學比較表達式:
- ?x == y :值x等于y。
- ?x <= y :值x小于等于y。
- ?x < y :值x小于y。
- ?x >= y :值x大于等于y。
- ?x > y :值x大于y。
也可以對文本數據使用表達式,但必須小心。跟正則表達式不同,表達式必須完全匹配。數據必須跟模式嚴格匹配
第一個測試沒有匹配任何記錄,因為第一個數據字段的值不在任何記錄中。第二個測試用值data11 匹配了一條記錄。
6.5 結構化命令
1. if 語句
gawk編程語言支持標準的 if-then-else 格式的 if 語句。你必須為 if 語句定義一個求值的條件,并將其用圓括號括起來。如果條件求值為 TRUE ,緊跟在 if 語句后的語句會執行。如果條件求值為 FALSE ,這條語句就會被跳過??梢杂眠@種格式:
if (condition) statement1也可以將它放在一行上,像這樣:
if (condition) statement1如果需要在 if 語句中執行多條語句,就必須用花括號將它們括起來。
gawk 的 if 語句也支持 else 子句,允許在 if 語句條件不成立的情況下執行一條或多條語句。這里有個使用 else 子句的例子
可以在單行上使用 else 子句,但必須在 if 語句部分之后使用分號
if (condition) statement1; else statement2以下是上一個例子的單行格式版本:
2.while 語句
while 語句為gawk程序提供了一個基本的循環功能。下面是 while 語句的格式:
while (condition) { statements }while 循環允許遍歷一組數據,并檢查迭代的結束條件。如果在計算中必須使用每條記錄中的多個數據值,這個功能能幫得上忙。
while 語句會遍歷記錄中的數據字段,將每個值都加到 total 變量上,并將計數器變量 i 增值。當計數器值等于 4 時, while 的條件變成了 FALSE ,循環結束,然后執行腳本中的下一條語句。這條語句會計算并打印出平均值。這個過程會在數據文件中的每條記錄上不斷重復
gawk編程語言支持在 while 循環中使用 break 語句和 continue 語句,允許你從循環中跳出。
break 語句用來在 i 變量的值為 2 時從 while 循環中跳出。do-while語句使用較少,在此不介紹。
3.for語句
for 語句是許多編程語言執行循環的常見方法。gawk編程語言支持C風格的 for 循環。
for( variable assignment; condition; iteration process)6.6 格式化打印
本文不做說明
6.7 內建函數
1.數學函數
在使用一些數學函數時要小心,因為gawk語言對于它能夠處理的數值有一個限定區間。如果超出了這個區間,就會得到一條錯誤消息
第一個例子會計算e的100次冪,雖然數值很大,但尚在系統的區間內。第二個例子嘗試計算e的1000次冪,已經超出了系統的數值區間,所以就生成了一條錯誤消息。
除了標準數學函數外,gawk還支持一些按位操作數據的函數。
- and(v1, v2) :執行值 v1 和 v2 的按位與運算。
- compl(val) :執行 val 的補運算。
- lshift(val, count) :將值 val 左移 count 位。
- or(v1, v2) :執行值 v1 和 v2 的按位或運算。
- rshift(val, count) :將值 val 右移 count 位。
- xor(v1, v2) :執行值 v1 和 v2 的按位異或運算
2.字符串函數
gawk編程語言還提供了一些可用來處理字符串值的函數:
3. 時間函數
gawk編程語言包含一些函數來幫助處理時間值:
時間函數常用來處理日志文件,而日志文件則常含有需要進行比較的日期。通過將日期的文本表示形式轉換成epoch時間(自1970-01-01 00:00:00 UTC到現在的秒數),可以輕松地比較日期。
下面是在gawk程序中使用時間函數的例子。
該例用 systime 函數從系統獲取當前的epoch時間戳,然后用 strftime 函數將它轉換成用戶可讀的格式,轉換過程中使用了shell命令 date 的日期格式化字符。
4.自定義函數
本文不做說明。
7.實例
舉例來說,我們手邊有一個數據文件,其中包含了兩支隊伍(每隊兩名選手)的保齡球比賽得分情況
每位選手都有三場比賽的成績,這些成績都保存在數據文件中,每位選手由位于第二列的隊名來標識。下面的腳本對每隊的成績進行了排序,并計算了總分和平均分。
#!/bin/bash for team in $(gawk -F, '{print $2}' scores.txt | uniq) dogawk -v team=$team 'BEGIN{FS=",";total=0}{if ($2==team){total += $3 + $4 + $5;}}END {avg = total / 6;print "Total for", team, "is", total, ",the average is",avg}' scores.txt donefor 循環中的第一條語句過濾出數據文件中的隊名,然后使用 uniq 命令返回不重復的隊名。for 循環再對每個隊進行迭代。for 循環內部的 gawk 語句進行計算操作。對于每一條記錄,首先確定隊名是否和正在進行循環的隊名相符。這是通過利用 gawk 的 -v 選項來實現的,該選項允許我們在gawk程序中傳遞shell變量。如果隊名相符,代碼會對數據記錄中的三場比賽得分求和,然后將每條記錄的值再相加,只要數據記錄屬于同一隊。
在循環迭代的結尾處,gawk代碼會顯示出總分以及平均分。輸出結果如下。
其中for循環的變量定義還有另外一種方式:
#!/bin/bash teams=$(gawk -F, '{print $2}' scores.txt | uniq) for team in ${teams[@]} dogawk -v team=$team 'BEGIN{FS=",";total=0}{if ($2==team){total += $3 + $4 + $5;}}END {avg = total / 6;print "Total for", team, "is", total, ",the average is",avg}' scores.txt done輸出的結果也是一樣的。
參考書籍:Linux命令行與shell腳本編程大全.第3版.pdf
總結
以上是生活随笔為你收集整理的linux的gawk命令的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: vscode中文插件失效解决方法
- 下一篇: CTF 内存取证 USB流量分析