TI:WTBD/Awk
Spis treści
Awk, skrócony opis
Program awk jest interpreterem prostego języka programowania, wyspecjalizowanego w kierunku dokonywania najrozmaitszych przekształceń na plikach danych, szczególnie zapisanych w postaci tekstowej. Instrukcje języka awk definiujące reguły operacji na danych mogą być zapisane w pliku (skrypcie), lub (w szczególnie prostych przypadkach) podane wprost na linii poleceń.
Istnieje szereg odmian awk-a, które na różne sposoby wzbogacają podstawową specyfikację języka zdefiniowaną w normie POSIX (gawk == GNU awk, mawk, nawk, ...). Pozostaniemy tu na poziomie ich części wspólnej. Warto jednak wiedzieć, że interpreter GNU awk jest swobodnie dostępny w postaci źródłowej (jako program w języku C) -- podobnie jak inne narzędzia z rodziny GNU, i jest programem przenośnym. Ponadto dołączony jest do niego bardzo dobry podręcznik użytkowania (w formacie texinfo), mogący doskonale służyć do nauki programowania w języku awk niezależnie od wykorzystywanej wersji interpretera. ([1])
Awk w zarysie
- Program w języku Awk składa się z ciągu instrukcji o postaci wzorzec { akcja } oraz (ewentualnie) definicji funkcji.
- Interpreter awk czyta sekwencyjnie pliki (lub strumień) wejściowy, traktując dane wejściowe jako ciąg rekordów, z których każdy składa się z pewnej liczby pól.
- Każdy przeczytany rekord danych jest kolejno dopasowywany do podanych w programie wzorców; w przypadku stwierdzenia zgodności z wzorcem, wykonywana jest podana po tym wzorcu akcja, w przeciwnym wypadku akcja ta zostaje pominięta.
- Akcją domyślną jest wypisanie zawartości aktualnego rekordu do strumienia stdout (tj. nie podanie żadnej akcji jest równoważne akcji print).
- Znaki białe są na ogół bez znaczenia, z tym że koniec linii zazwyczaj brany jest za koniec polecenia. Zaleca się użycie średnika jako końca jednostki składniowej. Bloki (polecenia złożone) ujmowane są w nawiasy klamrowe, jak w C.
- Komentarze zaczynają się od # i kończą z końcem linii.
Postać wzorców
- BEGIN, END -- wzorce specjalne, traktowane jako nie pasujące do żadnego rekordu. Efektem ich użycia jest wykonanie odp. akcji jeden raz, przed rozpoczęciem przetwarzania danych (BEGIN) lub po jego zakończeniu (END). Mogą występować w programie dowolnie wiele razy i w dowolnych pozycjach; użyteczne akcje dla tych wzorców to np. inicjalizacja zmiennych (BEGIN), wypisywanie nagłówków tabeli lub podsumowań.
- /wyrażenie regularne/ -- zgodne z nim są rekordy pasujące jako napisy do podanego wyrażenia regularnego; składnia wyrażeń regularnych jest w zasadzie analogiczna jak w przypadku stosowanych z programem (e)grep.
- dowolne wyrażenie języka Awk -- jego wartość obliczana jest na nowo dla każdego wczytanego rekordu danych, a akcja jest wykonywana gdy wartość wyrażenia jest niezerowa (dla wyrażeń arytmetycznych) lub niepusta (dla wyrażeń napisowych)
- Wzorzec1, Wzorzec2 -- para wzorców przedzielonych przecinkiem pasuje do wszystkich rekordów począwszy od pierwszego pasującego do Wzorzec1 a skończywszy na ostatnim pasującym do Wzorzec2
Składnia wyrażeń
- Wyrażenia arytmetyczne budowane są ze stałych liczbowych oraz zmiennych o wartościach liczbowych, z wykorzystaniem operatorów arytmetycznych (+, -, *, ^, /, %) (^ == potęgowanie, % == reszta z dzielenia)
- Wyrażenia przypisania oraz inkrementacji: po lewej stronie operatora przypisania wartości (=, +=, -=, *=, /=, %=, ^=) może stać nazwa zmiennej skalarnej, odwołanie do elementu tablicy (p. dalej), lub odwołanie do pola bieżącego rekordu (//$n//). Po prawej stronie: dowolne wyrażenie. Wartością wyrażenia przypisania jest wartość która zostaje przypisana. Podobnie działają operatory inkrementacji, o własnościach analogicznych jak w C (++, --).
- Wyrażenia napisowe -- stała napisowa ma postać napisu ujętego w cudzysłów ("napis"). Jedyną operacją tworzącą napis złożony jest konkatenacja (łączenie) stałych napisowych lub zmiennych o wartościach napisowych. Operator konkatenacji nie posiada oznaczenia, zaleca się jednak stosowanie nawiasów np. ("napis1" "napis2") == "napis1napis2"
- Wyrażenia logiczne buduje się z wyrażeń arytmetycznych i napisowych za pomocą operatorów porównywania (==, !=, <, <=, >=) i operatorów logicznych (&&, ||, !); operatory porównywania dla wyrażeń arytmetycznych działają analogicznie jak w języku C; napisy są porównywane leksykograficznie. Wartością wyrażenia logicznego jest liczba 1 (prawda) lub 0 (fałsz), znów podobnie jak w C. Jako argument wyrażenia logicznego, każda niezerowa liczba i każdy niepusty napis traktowane są jako równoważne 1. Napisowi pustemu odpowiada wartość logiczna fałsz (0). Innym elementem służącym do tworzenia wyrażeń logicznych są operatory dopasowania wyrażeń regularnych (~, !~); po lewej stronie przyjmują one wyrażenia o wartości napisowej, po prawej może wystąpić stałe wyrażenie regularne (/REGEXP/) lub wyrażenie o wartości napisowej, które zostanie potraktowane jako zapis wyrażenia regularnego (umożliwia to wykorzystywanie dynamicznie utworzonych wyrażeń regularnych).
- Wyrażenia warunkowe -- tworzone są za pomocą konstrukcji WYR1 ? WYR2 : WYR3 o znaczeniu analogicznym jak w C.
- Wywołania funkcji: mają postać funkcja(arg1, arg2, ...). Spacja przed otwarciem nawiasu jest niedozwolona! Awk posiada wbudowany zestaw standardowych funkcji matematycznych (sqrt, exp, log, sin, cos, atan2, rand, srand, int>/tt>). Istnieją również wbudowane funkcje operujące na napisach (index, length, match, split, sprintf, sub, gsub, gensub, substr, tolower, toupper), funkcje I/O (close, system), oraz funkcje związane z czasem (systime, strftime). Możliwe jest też definiowanie własnych funkcji w tekście programu.
- Definicja funkcji ma postać:
function NAZWA(PARAMETRY)
{
DEFINICJA
}
- W liście parametrów PARAMETRY należy uwzględnić zarówno parametry formalne funkcji, jak i jej zmienne lokalne; przy wywołaniu PARAMETRY inicjalizowane są kolejno wartościami parametrów aktualnych, a brakujące otrzymują jako wartość napis pusty. Definicje funkcji używanych w programie awk nie muszą występować przed ich użyciem.
Instrukcje sterujące
if (WARUNEK) AKCJA1 ; [ else AKCJA2 ]
while (WARUNEK) AKCJA
do AKCJA while (WARUNEK)
for (INICJALIZACJA, WARUNEK, INKREMENTACJA) AKCJA
break
continue
exit [KOD ZWRACANY]
Powyższe instrukcje sterujące działają analogicznie jak w języku C.
Uwaga: po wywołaniu exit, akcje odpowiadające wzorcom END są wykonywane.
next : powoduje przejście do przetwarzania kolejnego rekordu, z zaniechaniem dalszego przetwarzania rekordu bieżącego.
Adresowanie rekordów i pól
- $0 : zawartość bieżącego rekordu
- $n (dla n>0): zawartość n-tego pola bieżącego rekordu (jeżeli n przekracza indeks ostatniego pola w bieżącym rekordzie: napis pusty)
po znaku $ można umieścić wyrażenie arytmetyczne, niekoniecznie stałą (wyrażenia złożone należy obejmować nawiasami)
Zmienne specjalne
(podane zostaną tylko najczęściej używane)
- FS : separator pól (w danych wejściowych); napis jednoznakowy lub wyrażenie regularne. Domyślna wartość FS == " " ma specjalne znaczenie: separatorami są dowolnie długie ciągi spacji i kodów tabulacji (a więc zawartości pól nie będą miały spacji na początku ani na końcu). Wartość FS == "" (pusty napis) oznacza, że każdy znak rekordu będzie potraktowany jako pole.
- RS : separator rekordów (w danych wejściowych). Domyślna wartość: znak nowej linii. Wartość RS == "" oznacza, że rekordy są rozdzielone dowolnie długimi ciągami pustych linii.
- OFS, ORS : pełnią analogiczną rolę do FS, RS dla strumienia danych wyjściowych (wyprowadzanych instrukcją print, p. dalej).
- ARGC, ARGV : analogiczne do argc, argv w języku C, z tym, że nie uwzględniają opcji interpretowanych przez program awk (a jedynie nazwy plików podane na linii komend). Tablica ARGV indeksowana jest liczbami całkowitymi, od zera począwszy.
- NF : liczba pól w bieżącym rekordzie.
- NR/tt> : numer kolejny aktualnie przetwarzanego rekordu.
- FILENAME : nazwa aktualnie przetwarzanego pliku. FILENAME == "-" jeżeli dane pochodzą ze strumienia stdin.
Tablice
Alokacja zmiennych tablicowych w języku Awk jest automatyczna; nie istnieje deklaracja tablicy. Odwołanie do elementu tablicy ma postać NAZWA[INDEKS] i może występować zarówno po prawej, jak i po lewej stronie wyrażenia przypisania wartości zmiennej.
INDEKS może być dowolnym wyrażeniem skalarnym --- czyli o wartości liczbowej lub napisowej.
Odwołanie do nieprzypisanego elementu zwraca napis pusty (i przypisuje go jako wartość danemu elementowi tablicy).
Wyrażenie INDEKS in NAZWA zwraca prawdę (1) jeżeli NAZWA[INDEKS] posiada przypisaną wartość, fałsz (0) w wypadku przeciwnym.
Konstrukcja for (INDEKS in NAZWA) AKCJA umożliwia przeskanowanie wszystkich elementów tablicy NAZWA którym przypisano wartości.
delete NAZWA[INDEKS] usuwa element z tablicy (a nie przypisuje mu pusty napis!).
Wyprowadzanie danych
print ARG1, ARG2, ...
printf FORMAT, ARG1, ARG2, ...
== Składnia wywołania
awk OPCJE -f PLIK.PROGRAMU PLIKI ...
awk OPCJE 'tekst programu' PLIKI ...
Istnieje m. in. opcja umożliwiająca zmianę separatora pól (-F FS).
Możliwe jest ponadto przypisywanie wartości zmiennym Awk-a na linii poleceń: argumenty postaci NAZWA=WARTOSC są rozpoznawane jako wyrażenia przypisania i mają identyczny skutek jak zamieszczenie odp. przypisania jako akcji dla wzorca BEGIN (ale po wykonaniu akcji BEGIN zamieszczonych w tekście lub pliku programu). Argumenty postaci NAZWA=WARTOSC są (podobnie jak nazwy plików danych) umieszczane w tablicy ARGV.