自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

幫助你排序文本文件的Awk命令行或腳本

系統(tǒng) Linux
Awk 是一個(gè)強(qiáng)大的工具,可以執(zhí)行某些可能由其它常見(jiàn)實(shí)用程序(包括 sort)來(lái)完成的任務(wù)。

[[285761]]

Awk 是一個(gè)強(qiáng)大的工具,可以執(zhí)行某些可能由其它常見(jiàn)實(shí)用程序(包括 sort)來(lái)完成的任務(wù)。

Awk 是個(gè)普遍存在的 Unix 命令,用于掃描和處理包含可預(yù)測(cè)模式的文本。但是,由于它具有函數(shù)功能,因此也可以合理地稱(chēng)之為編程語(yǔ)言。

令人困惑的是,有不止一個(gè) awk。(或者,如果你認(rèn)為只有一個(gè),那么其它幾個(gè)就是克隆。)有 awk(由Aho、Weinberger 和 Kernighan 編寫(xiě)的原始程序),然后有 nawk 、mawk 和 GNU 版本的 gawk。GNU 版本的 awk 是該實(shí)用程序的一個(gè)高度可移植的自由軟件版本,具有幾個(gè)獨(dú)特的功能,因此本文是關(guān)于 GNU awk 的。

雖然它的正式名稱(chēng)是 gawk,但在 GNU+Linux 系統(tǒng)上,它的別名是 awk,并用作該命令的默認(rèn)版本。 在其他沒(méi)有帶有 GNU awk 的系統(tǒng)上,你必須先安裝它并將其稱(chēng)為 gawk,而不是 awk。本文互換使用術(shù)語(yǔ) awkgawk。

awk 既是命令語(yǔ)言又是編程語(yǔ)言,這使其成為一個(gè)強(qiáng)大的工具,可以處理原本留給 sort、cut、uniq 和其他常見(jiàn)實(shí)用程序的任務(wù)。幸運(yùn)的是,開(kāi)源中有很多冗余空間,因此,如果你面臨是否使用 awk 的問(wèn)題,答案可能是肯定的“隨便”。

awk 的靈活之美在于,如果你已經(jīng)確定使用 awk 來(lái)完成一項(xiàng)任務(wù),那么無(wú)論接下來(lái)發(fā)生什么,你都可以繼續(xù)使用 awk。這包括對(duì)數(shù)據(jù)排序而不是按交付給你的順序的永恒需求。

樣本數(shù)據(jù)集

在探索 awk 的排序方法之前,請(qǐng)生成要使用的樣本數(shù)據(jù)集。保持簡(jiǎn)單,這樣你就不會(huì)為極端情況和意想不到的復(fù)雜性所困擾。這是本文使用的樣本集:

  1. Aptenodytes;forsteri;Miller,JF;1778;Emperor
  2. Pygoscelis;papua;Wagler;1832;Gentoo
  3. Eudyptula;minor;Bonaparte;1867;Little Blue
  4. Spheniscus;demersus;Brisson;1760;African
  5. Megadyptes;antipodes;Milne-Edwards;1880;Yellow-eyed
  6. Eudyptes;chrysocome;Viellot;1816;Sothern Rockhopper
  7. Torvaldis;linux;Ewing,L;1996;Tux

這是一個(gè)很小的數(shù)據(jù)集,但它提供了多種數(shù)據(jù)類(lèi)型:

  • 屬名和種名,彼此相關(guān)但又是分開(kāi)的
  • 姓,有時(shí)是以逗號(hào)開(kāi)頭的首字母縮寫(xiě)
  • 代表日期的整數(shù)
  • 任意術(shù)語(yǔ)
  • 所有字段均以分號(hào)分隔

根據(jù)你的教育背景,你可能會(huì)認(rèn)為這是二維數(shù)組或表格,或者只是行分隔的數(shù)據(jù)集合。你如何看待它只是你的問(wèn)題,而 awk 只認(rèn)識(shí)文本。由你決定告訴 awk 你想如何解析它。

只想排序

如果你只想按特定的可定義字段(例如電子表格中的“單元格”)對(duì)文本數(shù)據(jù)集進(jìn)行排序,則可以使用 sort 命令。

字段和記錄

無(wú)論輸入的格式如何,都必須在其中找到模式才可以專(zhuān)注于對(duì)你重要的數(shù)據(jù)部分。在此示例中,數(shù)據(jù)由兩個(gè)因素定界:行和字段。每行都代表一個(gè)新的記錄,就如你在電子表格或數(shù)據(jù)庫(kù)轉(zhuǎn)儲(chǔ)中看到的一樣。在每一行中,都有用分號(hào)(;)分隔的不同的字段(將其視為電子表格中的單元格)。

awk 一次只處理一條記錄,因此,當(dāng)你在構(gòu)造發(fā)給 awk 的這指令時(shí),你可以只關(guān)注一行記錄。寫(xiě)下你想對(duì)一行數(shù)據(jù)執(zhí)行的操作,然后在下一行進(jìn)行測(cè)試(無(wú)論是心理上還是用 awk 進(jìn)行測(cè)試),然后再進(jìn)行其它的一些測(cè)試。最后,你要對(duì)你的 awk 腳本要處理的數(shù)據(jù)做好假設(shè),以便可以按你要的數(shù)據(jù)結(jié)構(gòu)提供給你數(shù)據(jù)。

在這個(gè)例子中,很容易看到每個(gè)字段都用分號(hào)隔開(kāi)。為簡(jiǎn)單起見(jiàn),假設(shè)你要按每行的第一字段對(duì)列表進(jìn)行排序。

在進(jìn)行排序之前,你必須能夠讓 awk 只關(guān)注在每行的第一個(gè)字段上,因此這是第一步。終端中 awk 命令的語(yǔ)法為 awk,后跟相關(guān)選項(xiàng),最后是要處理的數(shù)據(jù)文件。

  1. $ awk --field-separator=";" '{print $1;}' penguins.list
  2. Aptenodytes
  3. Pygoscelis
  4. Eudyptula
  5. Spheniscus
  6. Megadyptes
  7. Eudyptes
  8. Torvaldis

因?yàn)樽侄畏指舴菍?duì) Bash shell 具有特殊含義的字符,所以必須將分號(hào)括在引號(hào)中或在其前面加上反斜杠。此命令僅用于證明你可以專(zhuān)注于特定字段。你可以使用另一個(gè)字段的編號(hào)嘗試相同的命令,以查看數(shù)據(jù)的另一個(gè)“列”的內(nèi)容:

  1. $ awk --field-separator=";" '{print $3;}' penguins.list
  2. Miller,JF
  3. Wagler
  4. Bonaparte
  5. Brisson
  6. Milne-Edwards
  7. Viellot
  8. Ewing,L

我們尚未進(jìn)行任何排序,但這是良好的基礎(chǔ)。

腳本編程

awk 不僅僅是命令,它是一種具有索引、數(shù)組和函數(shù)的編程語(yǔ)言。這很重要,因?yàn)檫@意味著你可以獲取要排序的字段列表,將列表存儲(chǔ)在內(nèi)存中,進(jìn)行處理,然后打印結(jié)果數(shù)據(jù)。對(duì)于諸如此類(lèi)的一系列復(fù)雜操作,在文本文件中進(jìn)行操作會(huì)更容易,因此請(qǐng)創(chuàng)建一個(gè)名為 sort.awk 的新文件并輸入以下文本:

  1. #!/bin/gawk -f
  2.  
  3. BEGIN {
  4.         FS=";";
  5. }

這會(huì)將該文件建立為 awk 腳本,該腳本中包含執(zhí)行的行。

BEGIN 語(yǔ)句是 awk 提供的特殊設(shè)置功能,用于只需要執(zhí)行一次的任務(wù)。定義內(nèi)置變量 FS,它代表字段分隔符field separator,并且與你在 awk 命令中使用 --field-separator 設(shè)置的值相同,它只需執(zhí)行一次,因此它包含在 BEGIN 語(yǔ)句中。

awk 中的數(shù)組

你已經(jīng)知道如何通過(guò)使用 $ 符號(hào)和字段編號(hào)來(lái)收集特定字段的值,但是在這種情況下,你需要將其存儲(chǔ)在數(shù)組中而不是將其打印到終端。這是通過(guò) awk 數(shù)組完成的。awk 數(shù)組的重要之處在于它包含鍵和值。 想象一下有關(guān)本文的內(nèi)容;它看起來(lái)像這樣:author:"seth",title:"How to sort with awk",length:1200。諸如作者、標(biāo)題和長(zhǎng)度之類(lèi)的元素是鍵,跟著的內(nèi)容為值。

在排序的上下文中這樣做的好處是,你可以將任何字段分配為鍵,將任何記錄分配為值,然后使用內(nèi)置的 awk 函數(shù) asorti()(按索引排序)按鍵進(jìn)行排序。現(xiàn)在,隨便假設(shè)你想按第二個(gè)字段排序。

沒(méi)有被特殊關(guān)鍵字 BEGINEND 引起來(lái)的 awk 語(yǔ)句是在每個(gè)記錄都要執(zhí)行的循環(huán)。這是腳本的一部分,該腳本掃描數(shù)據(jù)中的模式并進(jìn)行相應(yīng)的處理。每次 awk 將注意力轉(zhuǎn)移到一條記錄上時(shí),都會(huì)執(zhí)行 {} 中的語(yǔ)句(除非以 BEGINEND 開(kāi)頭)。

要將鍵和值添加到數(shù)組,請(qǐng)創(chuàng)建一個(gè)包含數(shù)組的變量(在本示例腳本中,我將其稱(chēng)為 ARRAY,雖然不是很原汁原味,但很清楚),然后在方括號(hào)中分配給它鍵,用等號(hào)(=)連接值。

  1. {   # dump each field into an array
  2.     ARRAY[$2] = $R;
  3. }

在此語(yǔ)句中,第二個(gè)字段的內(nèi)容($2)用作關(guān)鍵字,而當(dāng)前記錄($R)用作值。

asorti() 函數(shù)

除了數(shù)組之外,awk 還具有一些基本函數(shù),你可以將它們用作常見(jiàn)任務(wù)的快速簡(jiǎn)便的解決方案。GNU awk中引入的函數(shù)之一 asorti() 提供了按鍵(索引)或值對(duì)數(shù)組進(jìn)行排序的功能。

你只能在對(duì)數(shù)組進(jìn)行填充后對(duì)其進(jìn)行排序,這意味著此操作不能對(duì)每個(gè)新記錄都觸發(fā),而只能在腳本的最后階段進(jìn)行。為此,awk 提供了特殊的 END 關(guān)鍵字。與 BEGIN 相反,END 語(yǔ)句僅在掃描了所有記錄之后才觸發(fā)一次。

將這些添加到你的腳本:

  1. END {
  2.     asorti(ARRAY,SARRAY);
  3.     # get length
  4.     j = length(SARRAY);
  5.    
  6.     for (i = 1; i <= j; i++) {
  7.         printf("%s %s\n", SARRAY[i],ARRAY[SARRAY[i]])
  8.     }
  9. }

asorti() 函數(shù)獲取 ARRAY 的內(nèi)容,按索引對(duì)其進(jìn)行排序,然后將結(jié)果放入名為 SARRAY 的新數(shù)組(我在本文中發(fā)明的任意名稱(chēng),表示“排序的 ARRAY”)。

接下來(lái),將變量 j(另一個(gè)任意名稱(chēng))分配給 length() 函數(shù)的結(jié)果,該函數(shù)計(jì)算 SARRAY 中的項(xiàng)數(shù)。

最后,使用 for 循環(huán)使用 printf() 函數(shù)遍歷 SARRAY 中的每一項(xiàng),以打印每個(gè)鍵,然后在 ARRAY 中打印該鍵的相應(yīng)值。

運(yùn)行該腳本

要運(yùn)行你的 awk 腳本,先使其可執(zhí)行:

  1. $ chmod +x sorter.awk

然后針對(duì) penguin.list 示例數(shù)據(jù)運(yùn)行它:

  1. $ ./sorter.awk penguins.list
  2. antipodes Megadyptes;antipodes;Milne-Edwards;1880;Yellow-eyed
  3. chrysocome Eudyptes;chrysocome;Viellot;1816;Sothern Rockhopper
  4. demersus Spheniscus;demersus;Brisson;1760;African
  5. forsteri Aptenodytes;forsteri;Miller,JF;1778;Emperor
  6. linux Torvaldis;linux;Ewing,L;1996;Tux
  7. minor Eudyptula;minor;Bonaparte;1867;Little Blue
  8. papua Pygoscelis;papua;Wagler;1832;Gentoo

如你所見(jiàn),數(shù)據(jù)按第二個(gè)字段排序。

這有點(diǎn)限制。最好可以在運(yùn)行時(shí)靈活選擇要用作排序鍵的字段,以便可以在任何數(shù)據(jù)集上使用此腳本并獲得有意義的結(jié)果。

添加命令選項(xiàng)

你可以通過(guò)在腳本中使用字面值 var 將命令變量添加到 awk 腳本中。更改腳本,以使迭代子句在創(chuàng)建數(shù)組時(shí)使用 var

  1. { # dump each field into an array
  2.     ARRAY[$var] = $R;
  3. }

嘗試運(yùn)行該腳本,以便在執(zhí)行腳本時(shí)使用 -v var 選項(xiàng)將其按第三字段排序:

  1. $ ./sorter.awk -v var=3 penguins.list
  2. Bonaparte Eudyptula;minor;Bonaparte;1867;Little Blue
  3. Brisson Spheniscus;demersus;Brisson;1760;African
  4. Ewing,L Torvaldis;linux;Ewing,L;1996;Tux
  5. Miller,JF Aptenodytes;forsteri;Miller,JF;1778;Emperor
  6. Milne-Edwards Megadyptes;antipodes;Milne-Edwards;1880;Yellow-eyed
  7. Viellot Eudyptes;chrysocome;Viellot;1816;Sothern Rockhopper
  8. Wagler Pygoscelis;papua;Wagler;1832;Gentoo

修正

本文演示了如何在純 GNU awk 中對(duì)數(shù)據(jù)進(jìn)行排序。你可以對(duì)腳本進(jìn)行改進(jìn),以便對(duì)你有用,花一些時(shí)間在gawk 的手冊(cè)頁(yè)上研究 awk 函數(shù)并自定義腳本以獲得更好的輸出。

這是到目前為止的完整腳本:

  1. #!/usr/bin/awk -f
  2. # GPLv3 appears here
  3. # usage: ./sorter.awk -v var=NUM FILE
  4.  
  5. BEGIN { FS=";"; }
  6.  
  7. { # dump each field into an array
  8.     ARRAY[$var] = $R;
  9. }
  10.  
  11. END {
  12.     asorti(ARRAY,SARRAY);
  13.     # get length
  14.     j = length(SARRAY);
  15.    
  16.     for (i = 1; i <= j; i++) {
  17.         printf("%s %s\n", SARRAY[i],ARRAY[SARRAY[i]])
  18.     }
  19. }

 

 

責(zé)任編輯:龐桂玉 來(lái)源: Linux中國(guó)
相關(guān)推薦

2019-02-13 09:20:13

Linux命令行more

2014-03-11 10:11:33

Linux命令more命令文本文件

2021-11-29 09:46:11

FileReaderJava開(kāi)發(fā)

2010-04-30 17:38:31

Unix文本

2009-09-04 15:56:35

寫(xiě)入文本文件

2009-08-06 18:33:45

C#處理文本文件

2009-09-02 19:13:08

C#處理文本文件

2015-06-17 14:28:15

Java查詢(xún)處理方法

2010-01-15 10:05:35

VB.NET文件對(duì)象

2009-08-26 11:53:56

C#打印文本文件

2009-09-02 19:08:03

C#實(shí)現(xiàn)讀取文本文件

2023-05-17 18:45:56

Linux文件

2019-05-23 09:48:43

Linux正則表達(dá)式文本文件

2010-05-13 17:43:43

IIS服務(wù)器

2009-08-19 17:44:15

C#操作文本文件

2010-02-01 14:26:50

C++讀寫(xiě)文本文件

2022-11-25 09:16:43

Linux命令

2009-08-12 17:59:48

C#讀取文本文

2009-08-20 09:15:20

C#操作文本文件

2009-08-20 10:17:27

C#操作文本文件
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)