Dvanácté cvičení – AWK – základy

AWK je mocnější příbuzný sedu, o kterém jsme měli desáté cvičení.

Jak spustit AWK:

awk 'prikazy' [vstupni_soubor1...]
awk -f soubor_s_prikazy [vstupni_soubor1...]
awk -v RS='X' ... nastaví do AWK zvenku proměnnou RS na hodnotu X


Tvar pravidla:

VZOR {příkazy}

Vzory jsou podobné, jako v sedu, ale umí toho víc:


Speciální proměnné:

Vstup a výstup:
Záznamy a pole v záznamu:

Pole

Chovají se jako asociativní pole, není potřeba nijak deklarovat ani alokovat, stačí přiřadit do nějakého políčka:


pole[42] = 42
pole[matfyz] = "MFF UK"
pole[2,7] = $0  # Fungují i vícerozměrná pole
print pole[50]  # Jenom odřádkuje, nijak si nestěžuje

Příkazy

Příkazy jsou od sebe odděleny koncem řádky nebo středníkem.

Příklady:

  1. Napište příkaz pro awk, který sečte všechny čísla na vstupu
  2. Vypište pomocí awk každou desátou řádku vstupu
  3. Vypište pomocí awk z každé řádky první a poslední slovo
  4. Napište awk skript/příkaz, který každou druhou řádku vstupu převede na velká písmena
  5. Napište awk skript/příkaz, který otočí pořadí slov na každé řádce
  6. Napište v AWK vlastní wc počítající počet řádků, počet slov a počet znaků a vypište je na konci. Stáhněte si soubor aircrafts2.csv (data o nehodách letadel), třeba pomocí wget http://kam.mff.cuni.cz/~setnicka/static/aircrafts2.csv
    • Spočítejte pomocí awk průměrný počet pasažérů na palubě (sloupec "Aboard")
    • Vypište havárie, kde zemřeli všichni na palubě (naformátujte výstup buď pomocí OFS nebo printf)
    • Spočítejte pomocí awk průměrné procento přeživších lidí na palubě a rozptyl tohoto čísla (rozptyl počítejte jako ${1\over n}\sum(x_i - E(x))^2$, abyste si vyzkoušeli pole)
  7. Vymyslete awk skript/příkaz, který bude mazat nadbytečné prázdné řádky – tedy každou posloupnost za sebou jdoucích prázdných řádků změní na jediný prázdný řádek.
  8. */?>

Řešení 5c


#!/usr/bin/awk -f
BEGIN {FS=";"}  # Načítáme csv oddělené středníky
NR>1 {
	# Některé řádky obsahují počet pasažérů 0 nebo NA, ty nechceme
	if ($7 != "NA" && $7 > 0) {
		# Odložíme si čísla do pole, abychom se k nim později dostali z ENDu
		pole[NR] = $6/$7
		sum += $6/$7
	}
}
END{
	prumer = sum/NR

	# Spočítáme rozptyl pomocí již spočítaného průměru
	for (i = 1; i <= NR; i++) rozptyl += (pole[i] - prumer) ** 2
	rozptyl /= NR

	printf("Prumer je %f, rozptyl je %f\n", prumer, rozptyl)
}
*/?>