Linux awk用法

来源:https://www.cnblogs.com/WebLinuxStudy/archive/2019/08/21/11391453.html
-Advertisement-
Play Games

在學習awk之前我們應該都學過sed,grep,tr,cut等等命令,這些命令都是為了方便我們對Linux下文本和數據的處理,但是我們會發現很多時候這些命令並不能一下子就完全解決我們的需求,很多時候我們都需要使用管道符結合這些命令來使用,今天我就給大家介紹一個命令awk,他就能很好的解決我們對文本和 ...


在學習awk之前我們應該都學過sed,grep,tr,cut等等命令,這些命令都是為了方便我們對Linux下文本和數據的處理,但是我們會發現很多時候這些命令並不能一下子就完全解決我們的需求,很多時候我們都需要使用管道符結合這些命令來使用,今天我就給大家介紹一個命令awk,他就能很好的解決我們對文本和數據處理的需求,使我們一條命令就解決很多問題。

一、awk命令簡介

awk被稱為文本處理三劍客之一,其名稱得自於它的創始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首個字母。實際上 AWK 的確擁有自己的語言: AWK 程式設計語言 , 三位創建者已將它正式定義為“樣式掃描和處理語言”。它允許您創建簡短的程式,這些程式讀取輸入文件、為數據排序、處理數據、對輸入執行計算以及生成報表,還有無數其他的功能。
所以說awk是一個強大的文本分析工具,相對於grep的查找,sed的編輯,awk在其對數據分析並生成報告時,顯得尤為強大。簡單來說awk就是把文件逐行的讀入,以空格為預設分隔符將每行切片,切開的部分再進行各種分析處理。

二、awk命令格式及選項

語法形式
awk [options] 'script' var=value file(s)
awk [options] -f scriptfile var=value file(s)
常用命令選項
-F fs fs指定輸入分隔符,fs可以是字元串或正則表達式,如-F:
-v var=value 賦值一個用戶定義變數,將外部變數傳遞給awk
-f scripfile 從腳本文件中讀取awk命令
-m[fr] val 對val值設置內在限制,-mf選項限制分配給val的最大塊數目;-mr選項限制記錄的最大數目。這兩個功能是Bell實驗室版awk的擴展功能,在標準awk中不適用。

三、awk的原理

awk 'BEGIN{ commands } pattern{ commands } END{ commands }'

第一步:執行BEGIN{ commands }語句塊中的語句;
第二步:從文件或標準輸入(stdin)讀取一行,然後執行pattern{ commands }語句塊,它逐行掃描文件,從第一行到最後一行重覆這個過程,直到文件全部被讀取完畢。
第三步:當讀至輸入流末尾時,執行END{ commands }語句塊。

BEGIN語句塊在awk開始從輸入流中讀取行之前被執行,這是一個可選的語句塊,比如變數初始化、列印輸出表格的表頭等語句通常可以寫在BEGIN語句塊中。

END語句塊在awk從輸入流中讀取完所有的行之後即被執行,比如列印所有行的分析結果這類信息彙總都是在END語句塊中完成,它也是一個可選語句塊。

pattern語句塊中的通用命令是最重要的部分,它也是可選的。如果沒有提供pattern語句塊,則預設執行{ print },即列印每一個讀取到的行,awk讀取的每一行都會執行該語句塊。

四、awk 基本用法

awk的調用有三種方式
1.命令行方式
awk [-F field-separator] 'commands' input-file(s)
其中,commands 是真正awk命令,[-F域分隔符]是可選的。 input-file(s) 是待處理的文件。
在awk中,文件的每一行中,由域分隔符分開的每一項稱為一個域。通常,在不指名-F域分隔符的情況下,預設的域分隔符是空格。

2.shell腳本方式
awk 'BEGIN{ print "start" } pattern{ commands } END{ print "end" }' file
一個awk腳本通常由:BEGIN語句塊、能夠使用模式匹配的通用語句塊、END語句塊3部分組成,這三個部分是可選的。任意一個部分都可以不出現在腳本中,腳本通常是被單引號或雙引號中,例如:

awk 'BEGIN{ i=0 } { i++ } END{ print i }' filename
awk "BEGIN{ i=0 } { i++ } END{ print i }" filename

3.將所有的awk命令插入一個單獨文件,然後調用

awk -f awk-script-file input-file(s)
其中,-f選項載入awk-script-file中的awk腳本,input-file(s)跟上面的命令行方式是一樣的。
我們通過幾個簡單的示例來進一步瞭解awk的用法

[root@localhost ~]# awk '{print $0}' /etc/passwd 
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
.........................................................................
[root@localhost ~]# echo 123|awk '{print "hello,awk"}'
hello,awk

[root@localhost ~]# awk '{print "hi"}' /etc/passwd
hi
hi
hi
hi
hi
hi
hi
hi
hi
.........................................................................

我們指定/etc/passwd作為輸出文件,執行awk時,它就會依次對/etc/passwd中的每一行執行print命令。
Linux awk用法
awk工作流程是這樣的:讀入有'\n'換行符分割的一條記錄,然後將記錄按指定的域分隔符劃分域,填充域,$0則表示所有域,$1表示第一個域,$n表示第n個域。預設域分隔符是"空白鍵" 或 "[tab]鍵",所以$1表示登錄用戶,$3表示登錄用戶ip,以此類推。如

列印/etc/passwd下所有的用戶名
[root@localhost ~]# awk -F: '{print $1}' /etc/passwd
root
bin
daemon
adm
........................................................................
列印/etc/passwd下所有的用戶名及UID
[root@localhost ~]# awk -F: '{print $1,$3}' /etc/passwd
root 0
bin 1
daemon 2
........................................................................
以username: XXX  uid: XXX格式輸出

[root@localhost ~]# awk -F: '{print "username: " $1 "\t\tuid: "$3}' /etc/passwd
username: root      uid: 0
username: bin       uid: 1
username: daemon        uid: 2
........................................................................

五、awk內置變數

變數描述
\$n 當前記錄的第n個欄位,欄位間由FS分隔
\$0 完整的輸入記錄
ARGC 命令行參數的數目
ARGIND 命令行中當前文件的位置(從0開始算)
ARGV 包含命令行參數的數組
CONVFMT 數字轉換格式(預設值為%.6g)ENVIRON環境變數關聯數組
ERRNO 最後一個系統錯誤的描述
FIELDWIDTHS 欄位寬度列表(用空格鍵分隔)
FILENAME 當前文件名
FNR 各文件分別計數的行號
FS 欄位分隔符(預設是任何空格)
IGNORECASE 如果為真,則進行忽略大小寫的匹配
NF 一條記錄的欄位的數目
NR 已經讀出的記錄數,就是行號,從1開始
OFMT 數字的輸出格式(預設值是%.6g)
OFS 輸出記錄分隔符(輸出換行符),輸出時用指定的符號代替換行符
ORS 輸出記錄分隔符(預設值是一個換行符)
RLENGTH 由match函數所匹配的字元串的長度
RS 記錄分隔符(預設是一個換行符)
RSTART 由match函數所匹配的字元串的第一個位置
SUBSEP 數組下標分隔符(預設值是/034)

示例

[root@localhost ~]# echo -e "line1 f2 f3\nline2 f4 f5\nline3 f6 f7" | awk '{print "Line No:"NR", No of fields:"NF, "$0="$0, "$1="$1, "$2="$2, "$3="$3}'
Line No:1, No of fields:3 $0=line1 f2 f3 $1=line1 $2=f2 $3=f3
Line No:2, No of fields:3 $0=line2 f4 f5 $1=line2 $2=f4 $3=f5
Line No:3, No of fields:3 $0=line3 f6 f7 $1=line3 $2=f6 $3=f7

使用print $NF可以列印出一行中的最後一個欄位,使用$(NF-1)則是列印倒數第二個欄位,其他以此類推:

[root@localhost ~]# echo -e "line1 f2 f3\n line2 f4 f5" | awk '{print $NF}'
f3
f5
[root@localhost ~]# echo -e "line1 f2 f3\n line2 f4 f5" | awk '{print $(NF-1)}'
f2
f4

統計/etc/passwd:文件名,每行的行號,每行的列數,對應的完整行內容:

[root@localhost ~]# awk  -F ':'  '{print "filename:" FILENAME ",linenumber:" NR ",columns:" NF ",linecontent:"$0}' /etc/passwd
filename:/etc/passwd,linenumber:1,columns:7,linecontent:root:x:0:0:root:/root:/bin/bash
filename:/etc/passwd,linenumber:2,columns:7,linecontent:bin:x:1:1:bin:/bin:/sbin/nologin
filename:/etc/passwd,linenumber:3,columns:7,linecontent:daemon:x:2:2:daemon:/sbin:/sbin/nologin

統計/etc/passwd文件中的命令行參數ARGC,文件行號FNR,欄位分隔符FS,一條記錄的欄位數目NF,已經讀出的記錄數(預設是行號)NR

[root@localhost ~]# awk -F: 'BEGIN{printf "%4s %4s %4s %4s %4s %4s\n","FILENAME","ARGC","FNR","FS","NF","NR";printf "---------------------------------------------\n"} {printf "%4s %4s %4s %4s %4s %4s\n",FILENAME,ARGC,FNR,FS,NF,NR}'  /etc/passwd
FILENAME ARGC  FNR   FS   NF   NR
---------------------------------------------
/etc/passwd    2    1    :    7    1
/etc/passwd    2    2    :    7    2
/etc/passwd    2    3    :    7    3

六、awk高級用法

1.awk賦值運算
賦值語句運算符:= += -= *= /= %= ^= **=

例如:a+=5;等價於a=a+5

[root@localhost ~]# awk 'BEGIN{a=5;a+=5;print a}'
10

2.awk正則運算
輸出包含有root的行,並列印用戶名和UID及原行內容

[root@localhost ~]# awk -F: '/root/ {print $1,$3,$0}' /etc/passwd
root 0 root:x:0:0:root:/root:/bin/bash
operator 11 operator:x:11:0:operator:/root:/sbin/nologin

我們發現找到了兩行,如果我們想找root開頭的行就要這樣寫:awk -F: '/^root/' /etc/passwd

3.awk三目運算

[root@localhost ~]# awk 'BEGIN{a="b";print a=="b"?"ok":"err"}'
ok
[root@localhost ~]# awk 'BEGIN{a="b";print a=="c"?"ok":"err"}'
err

三目運算其實就是一個判斷運算,如果為真則輸出?後的內容,如果為假則輸出:後的內容
4.awk的迴圈運用
if語句運用
[root@localhost ~]# awk 'BEGIN{ test=100;if(test>90){ print "vear good";} else{print "no pass";}}'
vear good
每條命令後用;結尾
while迴圈運用
計算從1累加到100的值

[root@localhost ~]# awk 'BEGIN{test=100;num=0;while(i<=test){num+=i; i++;}print num;}'
5050

for迴圈的運用
[root@localhost ~]# awk 'BEGIN{test=0;for(i=0;i<=100;i++){test+=i;}print test;}'
5050
do迴圈的運用
[root@localhost ~]# awk 'BEGIN{test=0;i=0;do{test+=i;i++}while(i<=100)print test;}'
5050

5.awk的數組運用
數組是awk的靈魂,處理文本中最不能少的就是它的數組處理。因為數組索引(下標)可以是數字和字元串在awk中數組叫做關聯數組(associative arrays)。awk 中的數組不必提前聲明,也不必聲明大小。數組元素用0或空字元串來初始化,這根據上下文而定。一般而言,awk中的數組用來從記錄中收集信息,可以用於計算總和、統計單詞以及跟蹤模板被匹配的次數等等。
顯示/etc/passwd的賬戶

awk -F: 'BEGIN {count=0;} {name[count] = $1;count++;}; END{for (i = 0; i < NR; i++) print i, name[i]}' /etc/passwd
0 root
1 bin
2 daemon
3 adm
4 lp
5 sync
........................................................................

6.awk字元串函數的運用
函數名 描述
sub 匹配記錄中最大、最靠左邊的子字元串的正則表達式,並用替換字元串替換這些字元串。如果沒有指定目標字元串就預設使用整個記錄。替換隻發生在第一次匹配的 時候
sub (regular expression, substitution string):
sub (regular expression, substitution string, target string)

實例:

         awk '{ sub(/test/, "mytest"); print }' testfile
         awk '{ sub(/test/, "mytest"); $1}; print }' testfile

第一個例子在整個記錄中匹配,替換隻發生在第一次匹配發生的時候。如要在整個文件中進行匹配需要用到gsub

第二個例子在整個記錄的第一個域中進行匹配,替換隻發生在第一次匹配發生的時候。
gsub 整個文檔中進行匹配
gsub (regular expression, substitution string)
gsub (regular expression, substitution string, target string)

實例:

         awk '{ gsub(/test/, "mytest"); print }' testfile
         awk '{ gsub(/test/, "mytest" , $1) }; print }' testfile

第一個例子在整個文檔中匹配test,匹配的都被替換成mytest。

第二個例子在整個文檔的第一個域中匹配,所有匹配的都被替換成mytest。
index 返回子字元串第一次被匹配的位置,偏移量從位置1開始
index(string, substring)

實例:

         awk '{ print index("test", "mytest") }' testfile

實例返回test在mytest的位置,結果應該是3。
substr 返回從位置1開始的子字元串,如果指定長度超過實際長度,就返回整個字元串
substr( string, starting position )
substr( string, starting position, length of string )

實例:

         awk '{ print substr( "hello world", 7,11 ) }' 

上例截取了world子字元串。
split 可按給定的分隔符把字元串分割為一個數組。如果分隔符沒提供,則按當前FS值進行分割
split( string, array, field separator )
split( string, array )

實例:

         awk '{ split( "20:18:00", time, ":" ); print time[2] }'

上例把時間按冒號分割到time數組內,並顯示第二個數組元素18。
length 返回記錄的字元數
length( string )
length

實例:

         awk '{ print length( "test" ) }' 
         awk '{ print length }' testfile

第一個實例返回test字元串的長度。

第二個實例返回testfile文件中第條記錄的字元數。
match 返回在字元串中正則表達式位置的索引,如果找不到指定的正則表達式則返回0。match函數會設置內建變數RSTART為字元串中子字元串的開始位 置,RLENGTH為到子字元串末尾的字元個數。substr可利於這些變數來截取字元串
match( string, regular expression )

實例:

         awk '{start=match("this is a test",/[a-z]+$/); print start}'
         awk '{start=match("this is a test",/[a-z]+$/); print start, RSTART, RLENGTH }'

第一個實例列印以連續小寫字元結尾的開始位置,這裡是11。

第二個實例還列印RSTART和RLENGTH變數,這裡是11(start),11(RSTART),4(RLENGTH)。
toupper和tolower 可用於字元串大小間的轉換,該功能只在gawk中有效
toupper( string )
tolower( string )

實例:

         awk '{ print toupper("test"), tolower("TEST") }'




您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1.僅適用於規則Excel:表頭和數據一一對應 2.涉及到Excel轉換為集合對象的部分代碼,完整npoi幫助類點擊查看 /// <summary> /// 預設把excel第一個sheet中的數據轉換為對象集合 /// </summary> /// <typeparam name="T"></ty ...
  • 首先需要獲得Azure上App-service 的porfile. 登錄portal 選到app,點擊Get publish pofile 將得到一個 ****.PublishSettings,註意這個文件還不是最後真正用於發佈的配置,還需要做如下操作,得到一個真正的發佈配置, 在VS 中打開項目, ...
  • EasyX 是針對 Visual C++ 的繪圖庫,在初學 C 語言實現圖形和游戲編程、圖形學、分形學等需要繪圖實踐的領域有一定應用。 EasyX 庫在 Visual C++ 中模擬了 Turbo C 引用繪圖庫頭文件的指令 #include ,並針對 Windows 的特點做了相應擴展。 系統支持 ...
  • 前提 入行已經7,8年了,一直想做一套漂亮點的自定義控制項,於是就有了本系列文章。 開源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control 如果覺得寫的還行,請點個 star 支持一下吧 歡迎前來交流探討: 企鵝群568015492 Nu ...
  • 1.HTML 或 2.Script:手動submit 3.UploadFileAction:Import是導入視圖 ...
  • 標題一、告別ASP.NET操作EXCEL的煩惱標題二、ASP.NET操作EXCEL 合併單元格 大全... cnblogs/hanzhaoxin/韓兆新的博客園ExcelReport第一篇:使用ExcelReport導出ExcelExcelReport第二篇:ExcelReport源碼解析Excel ...
  • 一、redis是什麼? 1.基於key-value的記憶體No sql 資料庫(非關係型資料庫) 2.讀寫性能非常好 二、redisd的數據類型有哪些?特點分別是什麼? 1)string 一個鍵對一個值2)list 一個鍵對多個值(有序 不唯一) 3)set 一個鍵對多個值(有序,唯一(去重)) 4) ...
  • 案例1:格式化重裝的電腦,接上耳機,音頻設置提示“麥克風未插入” 處理方法:更換新型號耳機調試正常後,更換原型號耳機使用正常 1、用新型號的耳機調試,跳出以下選擇框,選擇“麥克風”, 單擊“確定”; 2、如下圖,可以看到麥克風狀態是正常的 3、更換原型號耳機,Lync語音時麥克風和耳機功能恢復正常。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...