shell編程之awk命令詳解

1. awk 教程

1.1 調用 awk

awk 是一種強大的文本處理工具,在 Linux 系統中廣泛應用于日志分析、數據處理等場景。調用 awk 主要有以下三種方式:

1.1.1 命令行方式

基本語法為:

awk (-F filed-separator) 'commands' input-files

其中,-F用于指定分隔符,默認情況下,awk 以空格或制表符作為分隔符。commands是 awk 的命令,input-files則是要處理的文件。例如,我們有一個文件data.txt,內容如下:

apple 3 1.5
banana 5 2.0
cherry 2 1.8

如果我們想以空格為分隔符,打印每一行的第一個和第三個字段,可以使用以下命令:

awk '{print $1,$3}' data.txt

輸出結果為:

apple 1.5
banana 2.0
cherry 1.8

如果文件中的字段是以冒號分隔,我們就需要使用-F選項指定分隔符。比如有一個users.txt文件,內容為:

user1:password1:1001
user2:password2:1002
user3:password3:1003

要打印每個用戶的用戶名(第一個字段)和用戶 ID(第三個字段),命令如下:

awk -F: '{print $1,$3}' users.txt

輸出:

user1 1001
user2 1002
user3 1003

注意:

?單引號雙引號都行,但是要按照規范

場景單引號(')雙引號(")
純正則匹配推薦使用,語法簡潔,避免 Shell 干擾也可使用,但需注意轉義
包含 Shell 變量無法直接使用,需額外處理直接引用變量,Shell 先解析
正則包含特殊字符自動防止 Shell 解析,直接使用需用反斜杠轉義(如\$\+
避免引號嵌套錯誤適合正則中無單引號的場景適合正則中包含單引號的場景

1.1.2 腳本文件可執行方式

將所有 awk 命令插入一個文件,并使該文件可執行。同時,在腳本文件的首行使用#!/usr/bin/awk -f,這樣就可以通過直接鍵入腳本名稱來調用它。
例如,創建一個名為process.awk的文件,內容如下:

#!/bin/awk -f
{print $2}

然后為該文件添加可執行權限:

chmod +x process.awk

假設有一個input.txt文件,內容為:

one two three
four five six
seven eight nine

執行process.awk腳本處理input.txt文件:

./process.awk input.txt

輸出結果為:

two
five
eight

如果想要改變分隔符:

#!/bin/awk -f
# 設置字段分隔符為冒號
BEGIN { FS = ":" }   #FS 的英文全稱是Field Separator
{ print $1, $3 }

1.1.3 調用外部腳本方式

將所有的 awk 命令插入一個單獨文件,然后使用-f選項調用該腳本。語法為:

awk -f awk-script-file input-files

例如,有一個腳本文件calculate.awk,內容如下:

{
sum = $1 + $2
print sum
}

我們有一個數據文件numbers.txt,內容為:

3 5
2 7
4 6

執行命令:

awk -f calculate.awk numbers.txt

輸出:

8
9
10

1.2 awk 腳本

1.2.1 模式和動作

任何 awk 語句都由模式和動作組成。模式部分決定動作語句何時觸發及觸發條件,而動作則是對數據進行的具體操作。如果省略模式部分,動作將對每一行輸入數據都執行。
模式可以是條件語句、復合語句或正則表達式,其中有兩個特殊字段BEGINENDBEGIN語句用于設置計數、打印表頭之類的操作,它會在任何文本瀏覽動作之前執行。END語句則在 awk 完成對所有輸入文本的瀏覽動作后執行,通常用于打印輸出文本總數、結尾狀態標志等。
動作通常放在大括號{}內。動作最常見的是打印操作,但也可以包含更長的代碼,如if語句、循環語句及循環退出結構等。如果不指明動作,awk 將默認打印出所有輸入記錄。
例如,我們要處理一個成績文件grades.txt,內容如下:

Alice 85 90 78
Bob 70 65 80
Charlie 95 88 92

我們想在處理文件前打印表頭,處理文件時打印每個學生的姓名和平均成績,處理完后打印一個結束信息。可以使用以下 awk 腳本:

awk

BEGIN {
print "Student\tAverage Grade"
print "----------------------"
}
{
avg = ($2 + $3 + $4) / 3
print $1 "\t" avg
}
END {
print "----------------------"
print "End of Grades Report"
}

執行該腳本:

awk -f script.awk grades.txtsource files / command-line arguments must contain complete functions or rules
出現這個錯誤可能是你的大括號未閉合

輸出:

Student Average Grade
----------------------
Alice 84.3333
Bob 71.6667
Charlie 91.6667
----------------------
End of Grades Report

1.2.2 域和記錄

awk 執行時,會將輸入的每一行視為一條記錄,并且將記錄中的各個部分(以分隔符分隔)標記為$1$2……$n,這種方式稱為域標識。當需要指定多個域時,使用逗號,進行分隔,如$1,$3指定的是第一個域和第三個域。如果希望指定整行記錄,則可以使用$0
使用print命令執行打印操作,該命令需要用{}括起來。

1.2.2.1 抽取域

以之前的grades.txt文件為例,我們要打印每個學生的姓名(第一個域)和數學成績(第二個域),命令如下:

awk '{print $1,$2}' grades.txt

輸出:

Alice 85
Bob 70
Charlie 95
1.2.2.2 保存 awk 輸出

保存 awk 輸出結果主要有兩種方式:

  • 重定向到文件:這種方式下,屏幕不會顯示輸出內容,而是將結果保存到指定文件中。例如,將grades.txt文件中每個學生的姓名保存到students.txt文件中,命令為:

awk '{print $1}' grades.txt > students.txt

  • 使用管道將輸出結果傳給teetee命令可以將輸出同時顯示在屏幕上并保存到文件中。例如,將grades.txt文件中每個學生的總成績(三個成績之和)輸出到屏幕并保存到total_grades.txt文件中,命令如下:
awk '{sum=$2+$3+$4; print sum}' grades.txt | tee total_grades.txttee命令不可用的話,下載
yum install coreutils
1.2.2.3 使用標準輸入

可以通過多種方法將標準輸入作為 awk 的輸入源:

  • 直接在命令后跟上文件名,如awk '{print $0}' grades.txt,這里grades.txt的內容會作為標準輸入被 awk 讀取處理。
  • 使用<符號指定輸入文件,如awk '{print $0}' < grades.txt,效果與上一種方法相同。
1.2.2.4 打印所有記錄

要打印輸入文件的所有記錄,使用以下命令:

awk '{print $0}' input_file

其中input_file是要處理的文件名。

1.2.2.5 打印單獨記錄

只打印特定的域,如之前提到的只打印$1$4

awk '{print $1,$4}' input_file
1.2.2.6 自定義格式打印

我們可以在輸出內容中添加注釋、自定義分隔符等。例如,對于grades.txt文件,我們要在輸出學生姓名和平均成績時,在上方添加注釋 “Student Name” 和 “Average Score”,并使用制表符分隔,命令如下:

awk 'BEGIN {print "Student Name\tAverage Score\n------------------------------"} {avg = ($2 + $3 + $4) / 3; print $1 "\t" avg}' grades.txt

輸出:

Student Name Average Score
------------------------------
Alice 84.3333
Bob 71.6667
Charlie 91.6667
1.2.2.7 awk 錯誤信息提示

在使用 awk 時,如果遇到錯誤,可以從以下幾個方面排查:

  • 確保整個 awk 命令用單引號括起來,因為雙引號在 Shell 中可能會導致變量提前展開等問題,影響 awk 命令的執行。
  • 確保命令內所有引號成對出現,無論是單引號還是雙引號。
  • 確保用大括號{}括起動作語句,用括號()括起條件語句。
  • 檢查是否遺漏了大括號{},尤其是在包含多個動作或復雜條件判斷時。
1.2.2.8 awk 鍵盤輸入

如果在執行 awk 命令時沒有指定輸入文件,awk 會從鍵盤讀取輸入。輸入完成后,按Ctrl + D組合鍵結束輸入。例如,執行awk '{print $0}',然后在命令行輸入一些文本,每輸入一行按回車鍵,輸入完成后按Ctrl + D,awk 會打印出你輸入的每一行內容。

1.2.3 元字符

awk 支持一些元字符,用于模式匹配等操作,常見的元字符有\^$.()|*+?。其中+?在 grep 或 sed 中可能有不同的行為,但在 awk 中有其特定的含義:

  • +:匹配一個或一個以上前面的單字符。例如,/XY+Z/可以匹配XYZXYYYYZ等。
  • ?:匹配 0 個或一個前面的單字符。例如,/XY?Z/可以匹配XYZXZ
    例如,有一個文件strings.txt,內容為:
XZY
XYZY
XYYYYZY
XZ

要匹配包含XY后面跟著一個或多個Y再跟著Z的字符串,可以使用以下命令:

awk '/XY+Z/' strings.txt

輸出:

XYZY
XYYYYZY
[root@free ~]# awk '/XY?Z/' string.txt 
XZY
XYZY
XZ

1.2.4 條件操作符

awk 支持多種條件操作符,用于條件判斷:

操作符描述
<小于
<=小于等于
==等于
!=不等于
>大于
>=大于等于
~匹配正則表達式
!~不匹配正則表達式
1.2.4.1 匹配

使用~緊跟正則表達式可以匹配域,也可以使用if語句進行條件判斷,條件需要用()括起來。
例如,有一個文件employees.txt,內容如下:

John,Manager,50000
Alice,Engineer,45000
Bob,Engineer,48000

要查詢職位是工程師(Engineer)的員工信息(打印出$2匹配Engineer的行),可以使用以下兩種方式:

awk '{if ($2~/Engineer/) print $0}' employees.txt為什么不需要分號?
因為 if 語句控制下的 print 是同一個邏輯塊的一部分,不是獨立的語句。正則表達式的基本語法:
在 awk 中,正則表達式通常用 /pattern/ 表示,其中:
開頭的 /:標記正則表達式的開始;
結尾的 /:標記正則表達式的結束;
中間的 pattern:是具體的匹配模式(如 Engineer)。

或者

awk '$2 ~ /Engineer/' employees.txt
1.2.4.2 精確匹配

使用==并用雙引號括起條件可以進行精確匹配。例如,要查詢薪資為48000的員工信息:

awk '{if ($3 == "48000") print $0}' employees.txt
1.2.4.3 不匹配

使用!~緊跟正則表達式可以實現不匹配域的操作。例如,要查詢職位不是經理(Manager)的員工信息:

awk '{if ($2!~/Manager/) print $0}' employees.txt

或者

awk '$2 !~ /Manager/' employees.txt
1.2.4.4 比較

以比較薪資大小為例,要找出薪資大于45000的員工姓名和薪資:

awk '{if ($3 > 45000) print $1,$3}' employees.txt
1.2.4.5 各種匹配
  • 匹配Greengreen

awk '/(G|g)reen/' input_file

  • 匹配$1的第四個字符是a

awk '$1 ~ /^...a/' input_file

  • 匹配YellowBrown

awk '$4 ~ /Yellow|Brown/' input_file

  • 匹配以J開頭的行:

awk '$0 ~ /^J/' input_file
1.2.4.6 復合表達式

復合模式或復合操作符用于形成復雜的邏輯操作,復合表達式即為模式間通過使用復合操作符互相結合起來的表達式。常用的復合操作符有&&(邏輯與)和||(邏輯或):

  • &&(AND):符號兩邊的條件必須同時為真。例如,要查詢職位是工程師且薪資大于45000的員工信息:

awk '{if ($2 == "Engineer" && $3 > 45000) print $0}' employees.txt

  • ||(OR):符號兩邊的條件只要有一個為真即可。例如,要查詢職位是經理或者薪資大于48000的員工信息:

awk '{if ($2 == "Manager" || $3 > 48000) print $0}' employees.txt

1.2.5 awk 內置變量

awk 有許多內置變量,用于設置環境信息、獲取輸入輸出相關的狀態等。以下是一些常用的內置變量:

  • ARGC:表示命令行參數的個數。例如,執行awk -v var1=value1 -v var2=value2 -f script.awk file1 file2ARGC的值為5(包括awk命令本身、兩個-v選項及兩個文件名)。
  • ARGV:是一個數組,存儲命令行參數的排列。ARGV[0]通常是awk命令本身,ARGV[1]及后續元素為命令行參數。
  • FNR:與NR類似,用于記錄輸入的行數。不同之處在于,FNR在處理多個文件時,對每個文件都會從1開始計數,而NR是對所有輸入文件的總行數進行計數。例如,有兩個文件file1.txtfile2.txt,在處理file1.txt時,FNRNR1開始遞增,當處理完file1.txt開始處理file2.txt時,NR繼續遞增,而FNR又從1開始。
  • FS:用于指定輸入字段的分隔符。可以在BEGIN塊中定義,也可以使用-F選項在命令行指定。例如,BEGIN {FS=":"}將輸入字段分隔符設置為冒號。
  • RS:輸入的記錄分隔符,默認是換行符,即文本按一行一行輸入。可以修改這個變量來改變記錄的分隔方式。例如,BEGIN {RS="\n\n"}可以將連續兩個換行符作為記錄分隔符,適用于處理段落等以空行分隔的文本。
  • OFS:輸出字段分隔符,默認是空格。可以修改為其他字符,如制表符\t或逗號等。例如,BEGIN {OFS="|"}會將輸出的字段用豎線分隔。
  • ORS:輸出的記錄分隔符,默認為換行符,即處理結果也是一行一行輸出到屏幕。可以修改為其他字符,如BEGIN {ORS=","}會將輸出的記錄用逗號分隔,最后一個記錄后也會有逗號。
    例如,我們要統計一個文件中每行的字段數,并輸出行號、每行內容及字段數,使用以下腳本:

{
print NR, $0, NF
}

這里NR表示行號,NF表示當前行的字段數。假設文件example.txt內容為:

apple banana cherry
dog cat mouse

執行awk '{print NR, $0, NF}' example.txt,輸出:

1 apple banana cherry 3
2 dog cat mouse 3

再如,我們想以冒號為輸入分隔符,以逗號為輸出分隔符,打印文件data.csv的第一和第三個字段:

BEGIN {
FS=":"
OFS=","
}
{
print $1,$3
}

假設data.csv內容為:

1:apple:red
2:banana:yellow
3:grape:purple

執行該腳本,輸出:

1,red
2,yellow
3,purple

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/89840.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/89840.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/89840.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

服務器需要備案嗎?在哪些地區需要備案?

&#x1f3af; 服務器是否需要備案&#xff1f; 是否需要備案&#xff0c;關鍵看以下兩個因素&#xff1a; 服務器所在地&#xff08;機房位置&#xff09; 網站面向的訪問群體&#xff08;境內或境外&#xff09; &#x1f3f7; 中國大陸&#xff08;境內&#xff09;服務器…

HarmonyOS學習3---ArkUI

1、組件 1.1、基礎組件 1.2、布局容器 1.3、頁面導航 1.4、其他組件 2、ArkTs/C混合開發&#xff0c;高性能編碼 3、布局能力&交互歸一 4、實時開發預覽

Java學習第十五部分——MyBatis

目錄 一.概述 二.特點 三.組件 四.Mapper 五.配置文件 六.使用步驟 七.高級功能 八.優點缺點 九.項目實戰 1.打開idea創建一個Java項目&#xff0c;構建系統選“Maven”? 2.創建完成后若依賴報錯&#xff0c;可通過下載或重新加載來解決? 3.配置pom.xml文件&…

小企業如何搭建本地私有云服務器,并設置內部網絡地址提供互聯網訪問

在數字化時代&#xff0c;很多普通公司小企業規模的&#xff0c;利用本地小型服務器或計算機搭建私有云服務器&#xff0c;不僅可以提升數據管理效率&#xff0c;還能保障業務數據的安全性和靈活性。以下是為小企業量身定制的私有云服務器搭建指南&#xff0c;及最后附無公網IP…

MySQL 八股文【持續更新ing】

MySQL 八股文【持續更新ing】 文章目錄 MySQL 八股文【持續更新ing】前言一、MySQL的存儲引擎有哪些&#xff1f;他們之間有什么區別&#xff1f;二、MySQL InnoDB 引擎中的聚簇索引和非聚簇索引有什么區別&#xff1f;1.InnoDB 中的聚簇索引2.InnoDB 中的非聚簇索引 三、MySQL…

每日算法刷題Day42 7.5:leetcode前綴和3道題,用時2h

7. 3026.最大好子數組和(中等,學習) 3026. 最大好子數組和 - 力扣&#xff08;LeetCode&#xff09; 思想 1.給你一個長度為 n 的數組 nums 和一個 正 整數 k 。 如果 nums 的一個子數組中&#xff0c;第一個元素和最后一個元素 差的絕對值恰好 為 k &#xff0c;我們稱這個…

Linux操作系統之文件(四):文件系統(上)

前言&#xff1a; 我們前幾篇文章講了緩沖區與重定向的有關概念&#xff0c;這些設計是linux系統的核心機制&#xff0c;對系統性能、資源管理和用戶操作靈活性有重要意義。 不涉及一些硬件就不可能讓大家清楚地去理解文件系統&#xff0c;所以這篇文章&#xff0c;我將會從計…

java中,stream的filter和list的removeIf篩選速度比較

在 Java 里&#xff0c;Stream 的filter和 List 的removeIf篩選效率要依據具體情形來判斷。 1. 操作本質有別 Stream 的 filter&#xff1a; 它是一種中間操作&#xff0c;不會立刻執行&#xff0c;而是把篩選條件記錄下來。只有遇到終端操作時&#xff0c;才會開始處理元素。…

Python(28)Python循環語句指南:從語法糖到CPython字節碼的底層探秘

目錄 引言一、推導式家族全解析1.1 基礎語法對比1.2 性能對比測試 二、CPython實現揭秘2.1 字節碼層面的秘密2.2 臨時變量機制 三、高級特性實現3.1 嵌套推導式優化3.2 條件表達式處理 四、性能優化指南4.1 內存使用對比4.2 執行時間優化技巧 五、最佳實踐建議六、總結&#x1…

深度分析:Microsoft .NET Framework System.Random 的 C++ 復刻實現

深度分析&#xff1a;Microsoft .NET Framework Random 的 C 復刻實現 核心原理與算法結構 本實現基于 Knuth 減隨機數生成器&#xff08;Subtractive Random Number Generator&#xff09;&#xff0c;是 .NET Framework 中 System.Random 的精確復刻。其核心特點包括&#x…

[論文閱讀] 人工智能 | 在非CUDA硬件上運行幾何學習:基于Intel Gaudi-v2 HPU的PyTorch框架移植實踐

在非CUDA硬件上運行幾何學習&#xff1a;基于Intel Gaudi-v2 HPU的PyTorch框架移植實踐 論文標題&#xff1a;PyTorch-based Geometric Learning with Non-CUDA Processing Units: Experiences from Intel Gaudi-v2 HPUs arXiv:2507.01031 (cross-list from cs.LG) PyTorch-ba…

Python-多線程-threading

1 需求 2 接口 3 示例 4 參考資料 Python treading 模塊 | 菜鳥教程

2025年- H91-Lc199-- 62.不同路徑(多維動態規劃)--Java版

1.題目描述 2.思路 dp含義&#xff1a;代表到當前位置的路徑數 遞推公式&#xff1a;dp[i][j]dp[i-1][j]dp[i][j-1] dp數組初始化&#xff0c;我們要確保第一行和第一列是有值的. dp數組的遍歷順序&#xff1a;我們需要從左往右遍歷&#xff0c;從上往下遍歷。并且把第一行和第…

char 不是 Java 中的 2 字節(16 位)嗎? 為什么用 UTF-8 編碼寫入時,一個中文要占 3 個字節?

char 不是 Java 中的 2 字節&#xff08;16 位&#xff09;嗎&#xff1f; 為什么用 UTF-8 編碼寫入時&#xff0c;一個中文要占 3 個字節&#xff1f; ? 一、Java 中的 char 是什么&#xff1f; Java 的 char 是一個 固定大小的 2 字節&#xff08;16 位&#xff09;類型&am…

【Elasticsearch】檢索排序 分頁

檢索排序 & 分頁 1.測試數據準備2.排序功能2.1 簡單字段排序2.2 多字段排序2.3 日期排序 3.分頁功能3.1 基礎分頁3.2 深度分頁&#xff08;不推薦大數據量使用&#xff09;3.3 使用 search_after 進行高效分頁 4.綜合示例&#xff1a;高亮排序分頁5.實踐建議 1.測試數據準備…

Delta、Jackknife、Bootstrap

用班級平均身高的案例&#xff0c;展示 ?Delta、Jackknife、Bootstrap? 的完整計算過程。 ?0. 數據準備? ?原始數據&#xff08;4個學生的身高&#xff09;??&#xff1a; 真實均值&#xff08;目標統計量&#xff09;??&#xff1a; ?1. Delta 方法&#xff08;公式…

企業智腦技術架構設計:緊貼企業場景規劃面向未來的發展趨勢與實現路徑

摘要 本文深入探討了企業智腦技術架構的設計理念與發展趨勢&#xff0c;分析了當前企業智能化轉型的技術需求與挑戰&#xff0c;提出了一個面向未來的企業智腦技術架構設計方案。文章從底層技術支撐、核心能力構建、應用場景適配、安全合規保障以及未來發展路徑五個維度展開論…

新手向:Python方向講解

從NASA火星任務到TikTok推薦算法&#xff0c;從自動化腳本到量子計算&#xff0c;Python用import antigravity重新定義了編程邊界 一、設計哲學&#xff1a;優雅明確的編程禪學 Python之禪&#xff08;import this&#xff09;&#xff1a; 優美勝于丑陋&#xff08;Beautifu…

Chrome谷歌瀏覽器插件ModHeader,修改請求頭,開發神器

文章目錄一、介紹與下載二、使用一、介紹與下載 ModHeader顧名思義就是讓我們可以自定義HTTP請求頭或者是重寫響應頭&#xff0c;包括新增請求頭/響應頭或者覆蓋Chrome瀏覽器設置的請求頭的默認值&#xff0c;同時還可以根據URL Pattern來只對特定網站生效。 有條件的同學可以…

SEW:無監督預訓練在語音識別中的性能-效率權衡

摘要 本文研究了自動語音識別&#xff08;ASR&#xff09;中預訓練模型的性能-效率權衡問題。我們聚焦于 wav2vec 2.0&#xff0c;并形式化了多種影響模型性能和效率的架構設計。基于所有觀察結果&#xff0c;我們提出了 SEW&#xff08;Squeezed and Efficient Wav2vec&#…