AWK 是一種強大的文本處理工具,廣泛用于 Linux/Unix 系統中對文本文件或數據流進行操作。它能夠基于條件篩選、統計字段、重新排列數據等。主要特點包括:
2. AWK 的基本語法
2.1 AWK 程序的結構
AWK 程序的結構:
awk?'pattern?{?action?}'?file
2.2 常用內置變量
變量 | 含義 |
NR | 當前處理的行號 |
FNR | 當前文件的行號(處理多個文件時的相對行號) |
NF | 當前行的字段數(列數) |
2 | 第 1 列、第 2 列的值 |
$NF | 當前行的最后一列值 |
FS | 輸入字段分隔符(默認為空格) |
OFS | 輸出字段分隔符(默認空格) |
RS | 輸入記錄分隔符(默認為換行符) |
ORS | 輸出記錄分隔符(默認為換行符) |
ARGIND | 當前處理的文件在命令行參數中的索引 |
ARGC | 命令行參數的數量 |
ENVIRON | 存儲當前環境變量的關聯數組 |
FILENAME | 當前正在處理的文件名 |
SUBSEP | 數組下標分隔符(默認為?\034 ) |
RSTART | match ?函數匹配字符串的起始位置 |
RLENGTH | match ?函數匹配字符串的長度 |
以下是?常用內置變量?的補充說明,以 Markdown 格式輸出:
變量說明:
2.3 運行 AWK 程序
AWK 程序可以通過以下方式運行:
注意事項:
? 未指定文件時,AWK 從標準輸入讀取數據;
? 可同時處理多個文件;
2.4 基本輸出
2.5 高級輸出
printf 格式化輸出
printf
?可以格式化輸出內容,例如:
awk?'{?printf?"Name:?%s,?Age:?%d\n",?$1,?$2?}'?file.txt
排序輸出
結合?sort
?命令對輸出進行排序:
awk?'{?print?$1?}'?file.txt?|?sort
2.6 選擇/過濾行
按某列的值
按某幾列值的計算結果
按字符串匹配
不同方式的組合
BEGIN 和 END
2.7 計算
統計數量:工時超過 15 小時的員工人數
awk?'$3?>?15?{?count++?}?END?{?print?count?}'?file.txt
求和、求平均:平均工資
awk?'{?sum?+=?$2?}?END?{?print?"Average:",?sum/NR?}'?file.txt
處理文本:打印時薪最高的員工信息
awk?'$4?>?max?{?max?=?$4;?line?=?$0?}?END?{?print?line?}'?file.txt
字符串拼接(concatenation):在一行內打印所有員工名
awk?'{?names?=?names?$1?"?"?}?END?{?print?names?}'?file.txt
打印最后一行
awk?'{?last?=?$0?}?END?{?print?last?}'?file.txt
內置函數
2.8 控制流
If-Else
awk?'{?if?($1?>?50)?print?"High";?else?print?"Low"?}'?file.txt
While
awk?'{?i?=?1;?while?(i?<=?NF)?{?print?$i;?i++?}?}'?file.txt
For
awk?'{?for?(i?=?1;?i?<=?NF;?i++)?print?$i?}'?file.txt
2.9 數組
統計每列的總和:
awk?'{?for?(i?=?1;?i?<=?NF;?i++)?sum[i]?+=?$i?}?END?{?for?(i?in?sum)?print?"Column",?i,?"Sum:",?sum[i]?}'?file.txt
3. AWK 示例速查表
以下是常見 AWK 功能及其對應程序和類似命令:
編號 | 功能 | AWK 程序 | 類似命令 |
1 | 打印總行數 | END { print NR } | wc -l |
2 | 打印第 10 行 | NR == 10 { print } | sed -n '10p' |
3 | 打印最后一列 | { print $NF } | 無 |
4 | 打印最后一行的最后一列 | { f = $NF } END { print f } | tail -n1 |
5 | 打印有 4 列以上的行 | NF > 4 { print } | 無 |
6 | 打印最后一列的值大于 4 的行 | $NF > 4 { print } | 無 |
7 | 打印所有輸入的總字段數 | { nf += NF } END { print nf } | 無 |
8 | 打印包含關鍵字的總行數 | /keyword/ { n++ } END { print n } | grep -c 'keyword' |
9 | 打印第 1 列的最大值及對應的行 | $1 > max { max = $1; line = $0 } END { print max, line } | 無 |
10 | 打印列數大于 1 的行 | NF > 1 { print } | 無 |
11 | 打印長度大于 80 的行 | length($0) > 80 { print } | 無 |
12 | 打印每行的列數和該行內容 | { print NF, $0 } | 無 |
13 | 打印第 2 列和第 1 列 | { print $2, $1 } | 無 |
14 | 交換第 1 列和第 2 列 | { t = $1; $1 = $2; $2 = t; print } | 無 |
15 | 第 1 列替換為行號 | { $1 = NR; print } | 無 |
16 | 刪除第 2 列并打印 | { $2 = ""; print } | 無 |
17 | 倒序打印每行的字段 | { for (i=NF; i>0; i--) printf "%s ", $i; printf "\n" } | 無 |
18 | 計算每行的字段和 | { sum=0; for (i=1; i<=NF; i++) sum += $i; print sum } | 無 |
19 | 計算所有字段的總和 | { for (i=1; i<=NF; i++) sum += $i } END { print sum } | 無 |
20 | 將所有字段取絕對值并打印 | { for (i=1; i<=NF; i++) if ($i<0) $i = -$i; print } | 無 |
-
-
??基于模式匹配:?根據條件篩選數據。
-
??列操作能力:?簡單高效地處理文本列數據。
-
??輕量編程語言:?提供內置變量、循環、條件語句等編程功能。
-
相關資料
《AWK 編程語言》:
-
https://github.com/wuzhouhui/awk/blob/twoside/The_AWK_Programming_Language_zh_CN.pdf
-
??pattern:?指定操作的匹配規則,例如正則表達式、邏輯判斷等。
-
??action:?指滿足條件時要執行的操作,用?
{}
?包圍,例如打印、統計、替換等。 -
??file:?要處理的文本文件名稱。
-
NR 和 FNR 的區別:
-
??
NR
:累計行號,處理多個文件時行號會累加。 -
??
FNR
:當前文件的行號,處理多個文件時每個文件的行號從 1 開始重新計數。
-
-
FS 和 OFS 的作用:
-
??
FS
:指定輸入字段的分隔符,默認是空格。 -
??
OFS
:指定輸出字段的分隔符,默認是空格。
-
-
RS 和 ORS 的作用:
-
??
RS
:指定輸入記錄的分隔符,默認是換行符。 -
??
ORS
:指定輸出記錄的分隔符,默認是換行符。
-
-
?ENVIRON 的使用:
-
??
ENVIRON
?是一個關聯數組,用于訪問環境變量。例如:awk?'BEGIN?{?print?ENVIRON["HOME"]?}'
-
-
RSTART 和 RLENGTH:
-
? 這兩個變量與?
match
?函數配合使用,用于獲取匹配字符串的起始位置和長度。例如:awk?'BEGIN?{?str?=?"hello?world";?match(str,?/world/);?print?RSTART,?RLENGTH?}'
-
-
SUBSEP:
-
? 用于多維數組的下標分隔符,默認是?
\034
(非打印字符)。例如:awk?'BEGIN?{?arr["a",?"b"]?=?10;?print?arr["a",?"b"]?}'
-
-
ARGIND 和 ARGC:
-
??
ARGIND
:當前處理的文件在命令行參數中的索引(從 1 開始)。 -
??
ARGC
:命令行參數的數量。例如:awk?'BEGIN?{?print?ARGIND,?ARGC?}'?file1.txt?file2.txt
-
-
FILENAME:
-
? 當前正在處理的文件名。例如:
awk?'{?print?FILENAME,?$0?}'?file1.txt?file2.txt
-
-
2, ..., $NF:
-
??
$1
?表示第 1 列,$2
?表示第 2 列,依此類推。 -
??
$NF
?表示當前行的最后一列。
-
-
NF:
-
? 當前行的字段數(列數)。例如:
awk?'{?print?NF?}'?file.txt
-
-
RS 和 ORS 的高級用法:
-
? 可以修改?
RS
?和?ORS
?來處理非標準格式的文件。例如,將?RS
?設置為空字符串,以處理多行記錄:awk?'BEGIN?{?RS?=?""?}?{?print?$0?}'?file.txt
-
-
SUBSEP 的高級用法:
-
? 可以修改?
SUBSEP
?來定義多維數組的下標分隔符。例如:awk?'BEGIN?{?SUBSEP?=?":";?arr["a",?"b"]?=?10;?print?arr["a",?"b"]?}'
-
-
RSTART 和 RLENGTH 的高級用法:
-
? 結合?
match
?函數,可以提取匹配的子字符串。例如:awk?'BEGIN?{?str?=?"hello?world";?match(str,?/world/);?print?substr(str,?RSTART,?RLENGTH)?}'
-
-
ENVIRON 的高級用法:
-
? 可以遍歷?
ENVIRON
?數組,打印所有環境變量。例如:awk?'BEGIN?{?for?(key?in?ENVIRON)?print?key,?ENVIRON[key]?}'
-
-
?FILENAME 的高級用法:
-
? 在處理多個文件時,可以根據文件名執行不同的操作。例如:
awk?'{?if?(FILENAME?==?"file1.txt")?print?"File1:",?$0;?else?print?"File2:",?$0?}'?file1.txt?file2.txt
-
-
命令行直接運行:
awk?'pattern?{?action?}'?file
-
??
pattern
:匹配條件(可選)。 -
??
action
:滿足條件時執行的操作。 -
??
file
:要處理的文件。
-
-
腳本文件運行:
awk?-f?script.awk?file
示例:假設?
script.awk
?內容如下:{?print?$1?}
運行命令:
awk?-f?script.awk?file.txt
-
??
script.awk
:包含 AWK 程序的腳本文件。 -
??
file
:要處理的文件。
-
-
? 打印文件的所有內容:
awk?'{?print?$0?}'?file.txt
-
? 打印文件的第 1 列和第 3 列:
awk?'{?print?$1,?$3?}'?file.txt
-
? 打印第 2 列大于 50 的行:
awk?'$2?>?50?{?print?}'?file.txt
-
? 打印第 1 列和第 2 列之和大于 100 的行:
awk?'$1?+?$2?>?100?{?print?}'?file.txt
-
? 打印包含 "error" 的行:
awk?'/error/?{?print?}'?file.txt
-
? 打印第 2 列大于 50 且包含 "error" 的行:
awk?'$2?>?50?&&?/error/?{?print?}'?file.txt
-
??
BEGIN
?塊在處理輸入前執行,END
?塊在處理輸入后執行:awk?'BEGIN?{?print?"Start"?}?{?print?}?END?{?print?"End"?}'?file.txt
-
? 統計行數、單詞數、字符數:
awk?'{?chars?+=?length($0);?words?+=?NF?}?END?{?print?"Lines:",?NR,?"Words:",?words,?"Chars:",?chars?}'?file.txt
-