GNU/Linux >> Znalost Linux >  >> Linux

Awk jednolinky a skripty, které vám pomohou třídit textové soubory

Awk je všudypřítomný unixový příkaz pro skenování a zpracování textu obsahujícího předvídatelné vzory. Nicméně, protože obsahuje funkce, je také oprávněně nazýván programovacím jazykem.

Je matoucí, že existuje více než jeden awk. (Nebo, pokud věříte, že může být jen jeden, pak existuje několik klonů.) Je tu awk , původní program, který napsali Aho, Weinberger a Kernighan, a pak je tu nawk , mawk a verze GNU, gawk . GNU verze awk je vysoce přenosná, svobodná softwarová verze nástroje s několika jedinečnými funkcemi, takže tento článek je o GNU awk.

Zatímco jeho oficiální název je gawk, na systémech GNU+Linux má alias awk a slouží jako výchozí verze tohoto příkazu. Na jiných systémech, které se nedodávají s GNU awk, jej musíte nainstalovat a označovat jej jako gawk, nikoli awk. Tento článek používá termíny awk a gawk zaměnitelně.

Protože je awk jak příkazový, tak programovací jazyk, dělá z awk mocný nástroj pro úkoly, které by jinak mohly být tříděny , vyjmout , jedinečné a další běžné inženýrské sítě. Naštěstí je v open source dostatek prostoru pro redundanci, takže pokud stojíte před otázkou, zda použít nebo nepoužít awk, odpověď je pravděpodobně solidní "možná."

Krása flexibility awk spočívá v tom, že pokud jste se již zavázali používat awk pro určitý úkol, pak pravděpodobně můžete zůstat v awk bez ohledu na to, co se během cesty objeví. To zahrnuje věčnou potřebu třídit data jiným způsobem, než je objednávka, ve které vám byla doručena.

Ukázková sada

Než prozkoumáte metody řazení awk, vygenerujte ukázkovou datovou sadu, kterou chcete použít. Udržujte to jednoduché, abyste se nenechali rozptylovat okrajovými případy a nezamýšlenou složitostí. Toto je ukázková sada, kterou tento článek používá:

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

Je to malá datová sada, ale nabízí širokou škálu datových typů:

  • Jméno rodu a druhu, které jsou vzájemně spojeny, ale jsou považovány za samostatné
  • Příjmení, někdy s prvními iniciálami za čárkou
  • Celé číslo představující datum
  • Libovolný výraz
  • Všechna pole oddělená středníkem

V závislosti na vašem vzdělání to můžete považovat za 2D pole nebo tabulku nebo pouze za sbírku dat oddělenou řádky. Jak si to vymyslíte, je na vás, protože awk neočekává nic víc než text. Je na vás, abyste awk řekli, jak jej chcete analyzovat.

Cheat na řazení

Pokud chcete pouze seřadit textovou datovou sadu podle konkrétního, definovatelného pole (předpokládejte „buňku“ v tabulce), můžete použít příkaz sort.

Pole a záznamy

Bez ohledu na formát vašeho vstupu v něm musíte najít vzory, abyste se mohli soustředit na části dat, které jsou pro vás důležité. V tomto příkladu jsou data ohraničena dvěma faktory:řádky a poli. Každý nový řádek představuje nový záznam , jak byste pravděpodobně viděli ve výpisu z tabulky nebo databáze. V každém řádku jsou odlišná pole (představte si je jako buňky v tabulce), které jsou odděleny středníky (;).

Awk zpracovává jeden záznam po druhém, takže zatímco strukturujete pokyny, které dáte awk, můžete se soustředit pouze na jeden řádek. Určete, co chcete dělat s jedním řádkem, a poté to otestujte (buď mentálně nebo pomocí awk) na dalším řádku a několika dalších. Skončíte s dobrou hypotézou o tom, co musí váš skript awk udělat, aby vám poskytl požadovanou datovou strukturu.

V tomto případě je snadné vidět, že každé pole je odděleno středníkem. Pro jednoduchost předpokládejme, že chcete seznam seřadit podle prvního pole každého řádku.

Než budete moci třídit, musíte být schopni zaostřit awk pouze na první pole každého řádku, takže to je první krok. Syntaxe příkazu awk v terminálu je awk , za nimiž následují příslušné možnosti, za nimi váš příkaz awk a končící souborem dat, který chcete zpracovat.

$ awk --field-separator=";" '{print $1;}' penguins.list
Aptenodytes
Pygoscelis
Eudyptula
Spheniscus
Megadyptes
Eudyptes
Torvaldis

Protože oddělovač polí je znak, který má pro shell Bash zvláštní význam, musíte středník uzavřít do uvozovek nebo jej předcházet zpětným lomítkem. Tento příkaz je užitečný pouze k prokázání, že se můžete zaměřit na konkrétní pole. Můžete zkusit stejný příkaz s použitím čísla jiného pole a zobrazit obsah jiného „sloupce“ vašich dat:

$ awk --field-separator=";" '{print $3;}' penguins.list
Miller,JF
Wagler
Bonaparte
Brisson
Milne-Edwards
Viellot
Ewing,L

Ještě nebylo nic vyřešeno, ale toto je dobrý základ.

Skriptování

Awk je víc než jen příkaz; je to programovací jazyk s indexy, poli a funkcemi. To je důležité, protože to znamená, že můžete uchopit seznam polí, podle kterých chcete seřadit, uložit seznam do paměti, zpracovat jej a poté vytisknout výsledná data. Pro komplexní řadu akcí, jako je tato, je jednodušší pracovat v textovém souboru, proto vytvořte nový soubor s názvem sorter.awk a zadejte tento text:

#!/usr/bin/awk -f 

BEGIN {
        FS=";";
}

Tím se soubor vytvoří jako awk skript, který spouští řádky obsažené v souboru.

BEGIN statement je speciální nastavovací funkce poskytovaná awk pro úlohy, které je třeba provést pouze jednou. Definování vestavěné proměnné FS , což je zkratka pro oddělovač polí a je stejná hodnota, kterou jste nastavili v příkazu awk pomocí --field-separator , stačí, aby se to stalo jednou, takže je zahrnuto v BEGIN prohlášení.

Pole v awk

Již víte, jak shromáždit hodnoty konkrétního pole pomocí $ notaci spolu s číslem pole, ale v tomto případě jej musíte uložit do pole a ne tisknout na terminál. To se provádí pomocí pole awk. Důležité na poli awk je, že obsahuje klíče a hodnoty. Představte si pole o tomto článku; vypadalo by to nějak takto:autor:"seth",title:"How to sort with awk",length:1200 . Prvky jako autor a název a délka jsou klíče, přičemž následující obsah jsou hodnoty.

Výhodou v kontextu řazení je, že můžete přiřadit libovolné pole jako klíč a libovolný záznam jako hodnotu a poté použít vestavěnou funkci awk asorti() (seřadit podle indexu) pro řazení podle klíče. Prozatím předpokládejte svévolně, že pouze chcete seřadit podle druhého pole.

Awk prohlášení ne předcházejí speciální klíčová slova BEGIN nebo KONEC jsou smyčky, ke kterým dochází u každého záznamu. Toto je část skriptu, která skenuje data na vzory a podle toho je zpracovává. Pokaždé, když awk obrátí svou pozornost na záznam, příkazy v {} (pokud nepředchází BEGIN nebo KONEC ) jsou provedeny.

Chcete-li do pole přidat klíč a hodnotu, vytvořte proměnnou (v tomto příkladu skriptu ji nazývám ARRAY , který není nijak zvlášť originální, ale velmi přehledný) obsahující pole, a pak mu přiřadit klíč v závorkách a hodnotu se znaménkem rovná se (= ).

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

V tomto prohlášení je obsah druhého pole (2 $ ) se používají jako klíčový termín a aktuální záznam ($R ) se používá jako hodnota.

Funkce asorti()

Kromě polí má awk několik základních funkcí, které můžete použít jako rychlé a snadné řešení běžných úkolů. Jedna z funkcí představených v GNU awk, asorti() , poskytuje možnost seřadit pole podle klíče (nebo indexu ) nebo hodnotu.

Pole můžete třídit až po jeho naplnění, což znamená, že tato akce nesmí nastat s každým novým záznamem, ale pouze v poslední fázi vašeho skriptu. Za tímto účelem poskytuje awk speciální END klíčové slovo. Opačná hodnota k BEGIN , END příkaz se stane pouze jednou a pouze po naskenování všech záznamů.

Přidejte do svého skriptu toto:

END {
    asorti(ARRAY,SARRAY);
    # get length
    j = length(SARRAY);
   
    for (i = 1; i <= j; i++) {
        printf("%s %s\n", SARRAY[i],ARRAY[SARRAY[i]])
    }
}

Funkce asorti() funkce přebírá obsah ARRAY , seřadí jej podle indexu a umístí výsledky do nového pole s názvem SARRAY (libovolný název, který jsem pro tento článek vymyslel, znamená Sorted ARRAY ).

Dále proměnná j (jiný libovolný název) jsou přiřazeny výsledky length() funkce, která počítá počet položek v SARRAY .

Nakonec použijte pro smyčka pro iteraci každé položky v SARRAY pomocí printf() vytiskne každý klíč a poté odpovídající hodnotu tohoto klíče v POLE .

Spuštění skriptu

Chcete-li spustit skript awk, nastavte jej jako spustitelný:

$ chmod +x sorter.awk

A pak jej spusťte proti penguin.list ukázková data:

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

Jak vidíte, data jsou řazena podle druhého pole.

To je trochu omezující. Bylo by lepší mít možnost si za běhu vybrat, které pole chcete použít jako třídicí klíč, abyste mohli tento skript použít na jakoukoli datovou sadu a získat smysluplné výsledky.

Přidání možností příkazu

Proměnnou příkazu můžete přidat do skriptu awk pomocí doslovné hodnoty var ve vašem skriptu. Změňte skript tak, aby vaše iterační klauzule používala var při vytváření pole:

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

Zkuste skript spustit tak, aby se seřadil podle třetího pole pomocí -v var možnost, když jej spustíte:

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

Opravy

Tento článek ukázal, jak třídit data v čistém GNU awk. Skript lze vylepšit, takže pokud je to pro vás užitečné, věnujte nějaký čas zkoumání funkcí awk na manové stránce gawk a přizpůsobení skriptu pro lepší výstup.

Zde je zatím kompletní skript:

#!/usr/bin/awk -f
# GPLv3 appears here
# usage: ./sorter.awk -v var=NUM FILE

BEGIN { FS=";"; }

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

END {
    asorti(ARRAY,SARRAY);
    # get length
    j = length(SARRAY);
   
    for (i = 1; i <= j; i++) {
        printf("%s %s\n", SARRAY[i],ARRAY[SARRAY[i]])
    }
}

Linux
  1. Jak používat Awk a regulární výrazy k filtrování textu nebo řetězců v souborech

  2. Jak zjistit počet souborů v adresáři a podadresářích

  3. Jak používat příkaz Grep k vyhledání textu v souborech

  1. 10 základních linuxových příkazů, které potřebujete znát

  2. Binární a textový režim příkazu Md5sum?

  3. Jak používat příkaz Wireshark tshark pro vlastní porty a textové soubory

  1. Najít příkaz v Linuxu (Najít soubory a adresáře)

  2. Jak třídit soubory v Linuxu pomocí příkazu Sort

  3. Příkaz pro výpis všech souborů kromě . (tečka) a .. (tečka tečka)