Język AWK Kurs systemu UNIX 1
AWK Opracowany w laboratoriach Bella w 1978 przez Aho, Weinbergera i Kernighana Język do przetwarzania plików tekstowych Kurs systemu UNIX 2
AWK: pierwsza odsłona! AWK jest językiem programowania Można go jednak traktować jako proste połączenie funkcjonalności następujących programów: grep, do wybierania interesujących linii, cut, do wybierania interesujących kolumn, tr -s [:blank:], ponieważ domyślnym separatorem jest ciąg spacji i tabulacji. Kurs systemu UNIX 3
Czy AWK jest przestarzały? Czy prawdą jest, że: AWK < Perl < Python Chyba nie: AWK-a łatwiej się nauczyć, do małych zadań bardzo często wystarcza Kurs systemu UNIX 4
Pliki, rekordy, pola podstawowymi parametrami awk są pliki do przetworzenia. Pliki podzielone są na wiersze (rekordy), wiersze zaś na pola. Domyślnym separatorem jest ciąg białych znaków. Oczywiście separatorem może być dowolny znak. W takim formacie przechowywana jest większość unixowych plików konfiguracyjnych. Taki format mają również bardzo często dane wyjściowe poleceń (np. ls) Kurs systemu UNIX 5
Program w awk Podstawowy program: /wzorzec1/{akcja1} /wzorzec2/{akcja2} /wzorzec3/{akcja3} Dla każdej linijki, jeżeli pasuje ona do wzorca to wykonana jest odpowiednia akcja. Wzorcem może tekst, może być wyrażenie regularne, w tym miejscu może znaleźć się również dowolny warunek logiczny Zmienne o nazwach $1, $2, oznaczają kolejne pola. Można tych zmiennych używać w części {akcja}. Najprostsza akcja to print. Oznacza ona wypisanie całej linii. Kurs systemu UNIX 6
Dostęp do pól Zmienna $1 to pierwsze pole, $2 drugie itd. Cała bieżąca linia to $0. Przykład: wybranie z pliku dwóch kolumn i zamiana miejscami. awk '{print $3,$2 }' powyżej jako filtr, inna możliwość to awk -f program.awk dane_we1 dane_we2 > dane_wy Kurs systemu UNIX 7
Składnia wyrażeń regularnych ^ początek pola $ koniec pola. 1 dowolny znak alternatywa wzorców * 0 lub więcej wystąpień tego co przed + 1 lub więcej wystąpień tego co przed? 0 lub 1 powtórzenie tewgo co przed [ ] znak z zestawu ([abcd]) [^abcd] znak spoza zestawu () nawiasy grupują podwyrażenia Kurs systemu UNIX 8
Wyrażenia regularne Przykład: program wyświetlający te linie, które są liczbami /^[0-9]+(\.[0-9]+)?$/ { print $0 } W ten sposób uzyskujemy funkcjonalność programu grep. Kurs systemu UNIX 9
Warunki zamiast wzorców Zamiast wzorca może pojawić się warunek: awk '$4 > 100 {print $1*$4}' Inne warunki arytmetyczne: ==,!=, >, <, >=, <= Zyskujemy w ten sposób funkcjonalność arkusza kalkulacyjnego. Kurs systemu UNIX 10
Arytmetyka Operatory arytmetyczne: +, -, *, /, % (reszta z dzielenia), ^ (potęga) Funkcje matematyczne: sin, cos, log, exp, int (część całkowita), rand (wartość pseudolosowa) Nawiasy i priorytety bez niespodzianek. zm w wyrażeniu oznacza wartość zmiennej ($ niepotrzebny) Automatyczna konwersja z napisów do liczb: 1 + "123" = 124 1 + "Ala" = 1 Kurs systemu UNIX 11
Zmienne Przyjmują wartości liczbowe lub tekstowe Nie deklaruje się zmiennych (na początku 0 lub "") Podstawienie: x=x+1 lub x=x x Zagadka: Jaka jest wartość wyrażenia: ((2*2)(2*2))/4? Kurs systemu UNIX 12
Zmienne. Przykład Program obliczający sumę wielkości plików w kartotece: ls -l awk '/^-/{licznik = licznik+$5} END {print licznik}' Wzorce specjalne: BEGIN (przed pierwszą linią pliku) oraz END (po ostatniej). Kurs systemu UNIX 13
Wyrażenia regularne Przypominamy: wyglądają podobnie jak np. w programie sed, grupujemy podwyrażenia za pomocą normalnych nawiasów: "(" oraz ")", niestety nie ma \1, \2,... Mozna uzywać dopasowania w warunkach. wzorzec ~ tekst oznacza, że wzorzec pasuje do tekstu, natomiast wzorzec!~tekst wzorzec nie pasuje do tekstu. Fragment programu /wzorzec/{akcja} można zatem zapisać jako Kurs systemu UNIX 14
$0 ~ wzorzec {akcja} Kurs systemu UNIX 15
Zmienne wewnetrzne NR FNR FILENAME FS NF ARGC ARGV liczba przeczytanych rekordów to samo, ale w bieżącym pliku nazwa bieżącego pliku separator pol liczba pol w bieżącym rekordzie liczba argumentów lini poleceń Tablica argumentów linii poleceń Kurs systemu UNIX 16
Instrukcje strukturalne instrukcja for. Składnia jak w języku C: for(i1;i2;i3){ polecenia } instrukcja while. Składnia: while(w) { polecenia } instrukcja if Składnia: if (w) { polecenia } else { polecenia } next przejcie do nast. rekordu polecenie2 nigdy sie nie wykona { polecenie1 next; polecenie2; } Kurs systemu UNIX 17
Tablice Dynamiczny rozmiar nie trzeba deklarować możliwe tablice wielowymiarowe, do których odwołujemy się jak w Pascalu (a[x,y]) możliwe tablice asocjacyjne (indeksowane słowami) i potem pisać: x="ala"; print a[x]. Kurs systemu UNIX 18
Przykład: odwracanie kolejności wierszy { wiersze[nr] = $0 } END { licznik=nr; while (licznik > 0) { print wiersze[licznik]; licznik--; } } Kurs systemu UNIX 19
for dla tablic Można przeglądać tablice asocjacyjne. Składnia: for (z in T) { rob cos dla T[z] } Działa również dla tablic wielowymiarowych. Kurs systemu UNIX 20
Funkcje Definicja: function nazwa(lista parametrow) { } instrukcje; Parametry przekazywane przez wartość. Zwracane instrukcją return. Nie ma tych kłopotów z return co w bash-u, można zwracać dowolny napis lub tekst. Kurs systemu UNIX 21
Jak napisać skrypt w awk? Pierwsza linijka musi wyglądać mniej więcej tak: #!/usr/local/bin/awk -f Potem jest normalny program w awk. Parametry przekazywane są za pomocą zmiennych ARGC (liczba argumentów) oraz tablicy ARGV (same argumenty). Te parametry, które nie są nazwami plików powinny być obsłużone w bloku BEGIN i następnie skasowane, przykładowo: if ( /-/ ~ ARGV[i] ) { } # zapamietaj, ze opcja i jaka ARGV[i] = ""; Kurs systemu UNIX 22
Funkcje dzialajace na tekstach length długość tekstu. gsub(r,s,t) podstawia ciąg tekstowy t w ciągu s za każdym razem, gdy pasuje wyrażenie regularne r i zwraca liczbę dokonanych podstawień. split(tekst, T, znak) dzieli tekst na na części, które umieszcza w tablicy, zwraca ich liczbę. Przykładowo split("5-10-01",t,-") zwróci wartość 3, a ponadto ustali: T[1]="5", T[2]="10", T[3]="01" substr(s,m,n) oznacza n znaków z s poczynając od znaku m-tego, przy czym numeracja jest od 1. Kurs systemu UNIX 23
Zastosowanie length Za pomocą funkcji length można liczyć znaki w pliku. Przykładowo: { len += 1+length($0) } END {print "Znaków w pliku jest " len;} Rozwijając ten program w stronę wc dodalibyśmy: { wc += NF; } Linie już są liczone: robi to zmienna NR. Kurs systemu UNIX 24
Przykłady na gsub Można używać wersji dwuargumentowej, wtedy to w czym zmieniamy to $0. Można pisać filtry w ten sposób: { } gsub(/[0-9]+\.[0-9]+ /, "<real>") gsub(/[0-9]+ /,"<int> "); print ; # czyli print $0 Program linijkę 23.5 45.5 45 i tak dalej Kurs systemu UNIX 25
zmienia na <real> <real> <int> i tak dalej sub działa podobnie, ale podstawienie tylko raz. Dla gsub trzyargumentowego: zm="abrakadabra"; naco = "ba"; gsub(/a(b d)/,naco,zm); print zm; wypisze tekst: barakbabara. Kurs systemu UNIX 26
I tu w zasadzie moglibyśmy zakończyć Kurs systemu UNIX 27
Ale że zostało jeszcze trochę czasu... To omówimy Kurs systemu UNIX 28
Inne funkcje zwiazane z zamienianiem index(s,t) zwraca pozycję, na której po raz pierwszy w ciągu s pojawił się podciąg t, czyli np. index("c","rumcajs") zwraca 4. Jeżeli podciąg nie zostanie znaleziony to zwrócona zostanie wartość 0. Podobne działa funkcja match(s,t), ale pierwszy argument jest wyrażeniem regularnym. Wynik jest przechowywany w zmiennej RSTART, a długość dopasowanego fragmentu w zmiennej RLENGTH. Kurs systemu UNIX 29
Przykład Zadanie: chcemy zmienić każdą liczbę całkowitą n w tekście na tekst n (naprawd n!). Kurs systemu UNIX 30
Rozwiązanie: while ( match(/[0-9]+ /, linia)!= 0) { fragment = substr(linia,rstart,rlength-1); ile_zostalo = length(linia) - (RSTART+RLENGTH-1); linia = substr(linia,rstart,ile_zostalo); wynik = wynik fragment " (naprawd " fragment "!)" ; } wynik = wynik linia; Filtr ten zmieni zdanie: Pilni studenci dostan 5 a leniwi 2 na zdanie Kurs systemu UNIX 31
Pilni studenci dostan 5 (naprawde 5!) a leniwi 2 (naprawde 2!) Kurs systemu UNIX 32