6.11 Linux awk命令的高級玩法

      網友投稿 972 2025-03-31

      前面一節已經介紹了 awk 的基本用法,其實在 awk 腳本程序中,還支持使用一些編程語言,比如變量、數組、分支結構(if-then-else)、循環結構(while)、函數等,下面一一給大家介紹。

      awk 使用變量

      在 awk 的腳本程序中,支持使用變量來存取值。awk 支持兩種不同類型的變量:

      內建變量:awk 本身就創建好,用戶可以直接拿來用的變量,這些變量用來存放處理數據文件中的某些字段和記錄的信息。

      自定義變量:awk 支持用戶自己創建變量。

      awk 程序使用內建變量來引用程序數據里的一些特殊功能。常見的一些內建變量,包括上一節介紹的數據字段變量(

      awk 程序使用內建變量來引用程序數據里的一些特殊功能。常見的一些內建變量,包括上一節介紹的數據字段變量($0、$1、

      、、

      2...

      2...

      2...n)以及表 1 、表 2 中所示的這些變量。

      在表 1 中,變量 FS 和 OFS 定義了 awk 如何處理數據流中的數據字段。我們已經知道了如何使用變量 FS 來定義記錄中的字段分隔符,變量 OFS 具備相同的功能,只不過是用在 print 命令的輸出上,例如:

      [root@localhost ~]# cat data1 data11,data12,data13,data14,data15 data21,data22,data23,data24,data25 data31,data32,data33,data34,data35 [root@localhost ~]# awk 'BEGIN{FS=","; OFS="-"} {print ,,}' data1 data11-data12-data13 data21-data22-data23 data31-data32-data33 [root@localhost ~]# awk 'BEGIN{FS=","; OFS="--"} {print ,,}' data1 data11--data12--data13 data21--data22--data23 data31--data32--data33

      可以看到,print 命令會自動將 OFS 變量的值放置在輸出中的每個字段間。通過設置 OFS 變量,可以在輸出中使用任意字符串來分隔字段。

      FIELDWIDTHS 變量允許用戶不依靠字段分隔符來讀取記錄。在一些應用程序中,數據并沒有使用字段分隔符,而是被放置在了記錄中的特定列,這種情況下,必須設定 FIELDWIDTHS 變量來匹配數據在記錄中的位置。

      一旦設置了 FIELDWIDTH 變量,awk 就會忽略 FS 變量,并根據提供的字段寬度來計算字段,下面是個采用字段寬度而非字段分隔符的例子:

      [root@localhost ~]# cat data1b 1005.3247596.37 115-2.349194.00 05810.1298100.1 [root@localhost ~]# awk 'BEGIN{FIELDWIDTHS="3 5 2 5"}{print ,,,}' data1b 100 5.324 75 96.37 115 -2.34 91 94.00 058 10.12 98 100.1

      6.11 Linux awk命令的高級玩法

      注意,一旦設定了 FIELDWIDTHS 變量的值,就不能再改變了,因此,這種方法并不適用于變長的字段。

      變量 RS 和 ORS 定義了 awk 程序如何處理數據流中的字段,默認情況下,awk 將 RS 和 ORS 設為換行符。默認的 RS 值表明,輸入數據流中的每行新文本就是一條新紀錄。 有時,你會在數據流中碰到占據多行的字段。典型的例子是包含地址和電話號碼的數據,其中地址和電話號碼各占一行,例如:

      Riley Mullen 123 Main Street Chicago, IL 60601 (312)555-1234

      如果你用默認的 FS 和 RS 變量值來讀取這組數據,awk 就會把每行作為一條單獨的記錄來讀取,并將記錄中的空格當作字段分隔符,這并不是用戶想要的。

      要解決這個問題,只需把 FS 變量設置成換行符,這就表明數據流中的每行都是一個單獨的字段,每行上的所有數據都屬于同一個字段;與此同時,把 RS 變量設置成空字符串,然后在數據記錄間留一個空白行,awk 會把每個空白行當作一個記錄分隔符。例如:

      [root@localhost ~]# cat data2 Riley Mullen 123 Main Street Chicago, IL 60601 (312)555-1234 Frank Williams 456 Oak Street Indianapolis, IN 46201 (317)555-9876 Haley Snell 4231 Elm Street Detroit, MI 48201 (313)555-4938 [root@localhost ~]# awk 'BEGIN{FS="\n"; RS=""} {print $1,$4}' data2 Riley Mullen (312)555-1234 Frank Williams (317)555-9876 Haley Snell (313)555-4938

      其中,FNR 和 NR 變量雖然類似,但又略有不同。FNR 變量含有當前數據文件中已處理過的記錄數,NR 變量則含有已處理過的記錄總數。舉個例子:

      [root@localhost ~]# cat data1 data11,data12,data13,data14,data15 data21,data22,data23,data24,data25 data31,data32,data33,data34,data35 [root@localhost ~]# awk ' \> BEGIN {FS=","} \> {print $1,"FNR="FNR,"NR="NR} \> END{print "There were",NR,"records processed"}' data1 data1 data11 FNR=1 NR=1 data21 FNR=2 NR=2 data31 FNR=3 NR=3 data11 FNR=1 NR=4 data21 FNR=2 NR=5 data31 FNR=3 NR=6 There were 6 records processed

      由此可以看出,當只使用一個數據文件作為輸入時,FNR 和 NR 的值是相同的;如果使用多個數據文件作為輸入,FNR 的值會在處理每個數據文件時被重置,而 NR 的值則會繼續計數直到處理完所有的數據文件。

      和其他典型的編程語言一樣,awk 允許用戶定義自己的變量在腳本程序中使用。awk 自定義變量名可以是任意數目的字母、數字和下劃線,但不能以數字開頭。更重要的是,awk 變量名區分大小寫。

      舉個簡單的例子:

      [root@localhost ~]# awk ' \> BEGIN{ \> testing="This is a test" \> print testing \> testing=45 \> print testing \> }' This is a test 45

      可以看到,print 語句的輸出是 testing 變量的當前值。

      也可以用 awk 命令行來給程序中的變量賦值,這允許我們在正常的代碼之外賦值,即時改變變量的值,比如:

      [root@localhost ~]# cat script1 BEGIN{FS=","} {print $n} [root@localhost ~]# awk -f script1 n=2 data1 data12 data22 data32 [root@localhost ~]# awk -f script1 n=3 data1 data13 data23 data33

      需要注意的是,使用命令行參數來定義變量值會有一個問題,即設置了變量后,這個值在代碼的 BEGIN 部分不可用,如下所示:

      [root@localhost ~]# cat script2 BEGIN{print "The starting value is",n; FS=","} {print $n} [root@localhost ~]# awk -f script2 n=3 data1 The starting value is data13 data23 data33

      解決這個問題,可以用 -v 命令行參數,它可以實現在 BEGIN 代碼之前設定變量。在命令行上,-v 命令行參數必須放在腳本代碼之前,如下所示:

      [root@localhost ~]# awk -v n=3 -f script2 data1 The starting value is 3 data13 data23 data33

      awk 使用數組

      為了在單個變量中存儲多個值,許多編程語言都提供數組,awk 使用關聯數組提供數組功能。

      關聯數組跟數字數組不同之處在于,它的索引值可以是任意文本字符串。用戶不需要用連續的數字來標識數組中的數據元素;相反,關聯數組用各種字符串來引用值。每個索引字符串都必須能夠唯一地標識出賦給它的數據元素。

      如果你熟悉其他編程語言的話,其實關聯數組和散列表、字典的用法類似。

      在 awk 腳本程序中,定義一個數組變量可以使用標準復制語句,其基本格式為:

      var[index]=element

      其中,var 是數組名,index 是關聯數組的索引值,element 是數據元素值。例如:

      capital["Illinois"] = "Springfield" capital["Indiana"] = "Indianapolis" capital["Ohio"] = "Columbus"

      在引用數組變量時,必須用索引值(index)來提取相應的數據元素值,例如:

      [root@localhost ~]# awk 'BEGIN{ \> capital["Illinois"] = "Springfield" \> print capital["Illinois"] \> }' Springfield

      數組變量也是變量,也可以使用其進行基本的算術運算,例如:

      [root@localhost ~]# awk 'BEGIN{ \> var[1] = 34 \> var[2] = 3 \> total = var[1] + var[2] \> print total \> }' 37

      在 awk 中遍歷關聯數組,可以用 for 語句的一種特殊形式:

      for (var in array) { statements }

      這個 for 語句會在每次循環時將關聯數組 array 的下一個索引值賦給變量 var,然后執行一遍 statements。

      再次強調,整個遍歷過程中,傳給 var 的都是每個數組元素的索引值(也就是 index),不是數組元素的值。

      舉個例子:

      [root@localhost ~]# awk 'BEGIN{ \> var["a"] = 1 \> var["g"] = 2 \> var["m"] = 3 \> var["u"] = 4 \> for (test in var) \> { \> print "Index:",test," - Value:",var[test] \> } \> }' Index: u - Value: 4 Index: m - Value: 3 Index: a - Value: 1 Index: g - Value: 2

      注意,索引值不會按任何特定順序返回,但它們都能夠指向對應的數據元素值。

      awk腳本程序還支持從關聯數組中刪除某個數組索引,使用 delete 命令就可以,此命令會從數組中刪除指定的索引值及相關的數據元素的值。

      delete 命令的基本格式如下:

      delete array[index]

      舉個例子:

      [root@localhost ~]# awk 'BEGIN{ \> var["a"] = 1 \> var["g"] = 2 \> for (test in var) \> { \> print "Index:",test," - Value:",var[test] \> } \> delete var["g"] \> print "---" \> for (test in var) \> { \> print "Index:",test," - Value:",var[test] \> } \> }' Index: a - Value: 1 Index: g - Value: 2 \--- Index: a - Value: 1

      需要注意的是,一旦從關聯數組中刪除了索引值,就沒法再用它來提取元素值。

      awk使用分支結構

      awk 支持標準的 if-then-else 格式的 if 語句,其基本格式為:

      if (condition) statement1 else statements

      也可以將它放在一行上,像這樣:

      if (condition) statement1;else statement2

      舉個簡單的例子:

      [root@localhost ~]# cat data4 10 5 13 50 34 [root@localhost ~]# awk '{if ($1 > 20) print $1 * 2; else print $1 / 2}' data4 5 2.5 6.5 100 68

      awk使用循環結構

      awk 腳本程序中,可以使用 while、do-while、for 這 3 種循環結構,它們各自的基本格式分別如表 3 所示。

      awk使用函數

      和內建變量類似,awk 也提供了不少內建函數,可進行一些常見的數學、字符串以及時間函數運算,如表 4 所示。

      時間戳指的是格林威治時間,即從 1970年1月1日8時1起到現在的總秒數。

      除了awk 中的內建函數,還可以在 awk 腳本程序中自定義函數,創建自定義函數的基本格式為:

      function 函數名(參數1,參數2,...) { 運行代碼; }

      注意,自定義函數的函數名必須能夠唯一標識此函數,換句話說,在同一個 awk 腳本程序中,多個函數的函數名不能相同。同時,函數的參數可以有多個(0 個、1 個或多個)。

      例如:

      function printthird() { print $3 }

      此函數會打印記錄中的第三個數據字段。

      函數還能用 return 語句返回值,例如:

      function myrand(limit) { return int(limit * rand()) }

      需要注意的是,在定義函數時,它必須出現在所有代碼塊之前(包括 BEGIN 和 END代碼塊)。

      awk 提供了一種途徑來將多個函數放到一個庫文件中,這樣用戶就能在所有的 awk 腳本程序中使用了。為了方便大家理解,下面給大家舉個實例。

      首先,我們需要創建一個存儲所有 awk 函數的文件:

      [root@localhost ~]# cat funclib function myprint() { printf "%-16s - %s\n", $1, $4 } function myrand(limit) { return int(limit * rand()) } function printthird() { print $3 }

      要想讓 awk 成功讀取 funclib 函數庫文件,就需要使用 -f 選項,但此選項無法和 awk 腳本程序同時放到命令行中一起使用。因此,要使用庫函數文件,只能再創建一個腳本程序文件,例如:

      [root@localhost ~]# cat script4 BEGIN{ FS="\n"; RS=""} { myprint() } [root@localhost ~]# awk -f funclib -f script4 data2 Riley Mullen - (312)555-1234 Frank Williams - (317)555-9876 Haley Snell - (313)555-4938

      linux 數據結構

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:數據統計分析(數據統計分析法)
      下一篇:為什么項目符號后有空格,還沒有辦法弄掉(為什么項目符號后總有空格)
      相關文章
      亚洲AV综合色区无码另类小说 | 亚洲精品97久久中文字幕无码| 久久精品亚洲中文字幕无码麻豆 | 亚洲啪啪AV无码片| 亚洲娇小性色xxxx| 亚洲影视一区二区| 亚洲另类图片另类电影| 亚洲国产成人九九综合| 91亚洲精品自在在线观看| 亚洲午夜精品在线| 亚洲jizzjizz在线播放久| 最新国产精品亚洲| 亚洲男同gay片| 亚洲色最新高清av网站| 亚洲av无码专区在线观看亚| 亚洲AV无码一区二区乱子仑| 国产成人综合久久精品亚洲| 亚洲精品成a人在线观看| 亚洲精品网站在线观看不卡无广告| 亚洲色大成网站www永久网站| 亚洲精品视频在线| 亚洲AV无码一区二区三区在线观看| 亚洲国产成人a精品不卡在线| 亚洲中文字幕精品久久| 亚洲视频在线观看不卡| 亚洲AV永久无码区成人网站| 亚洲国产高清在线一区二区三区| 亚洲日韩精品国产3区| 亚洲最大的成网4438| 久久亚洲精品中文字幕三区| 亚洲成?v人片天堂网无码| 亚洲情a成黄在线观看动漫尤物| 亚洲伊人久久大香线蕉综合图片 | 67194在线午夜亚洲| 久久丫精品国产亚洲av不卡| 在线亚洲97se亚洲综合在线 | 亚洲VA中文字幕不卡无码| 久久久久亚洲AV综合波多野结衣| 亚洲av乱码一区二区三区按摩 | 亚洲一区二区三区在线网站| 亚洲天天在线日亚洲洲精|