Dziś jest sobota, 10 stycznia 2009 roku (z kalendarza...)

Język AWK

Icon

12.01.2008, 19:24

Arch Linux

Komentarze (2)

Powrót

Tematem dzisiejszego wpisu będzie interpretowany język programowania AWK. Został opracowany w 1977 roku przez autora kilku podręczników informatyki teoretycznej, Alfreda V. Aho, Petera Weinbergera oraz Briana Kerrighana. Jego głównym przeznaczeniem jest wyszukiwanie i przetwarzanie wzorców. Dostępny jest w niemal każdym systemie uniksowym jako część standardu POSIX i znacząco upraszcza wiele operacji wykonywanych w konsoli. Jego składnia jest bardzo podobna do języka C. Jeżeli znasz ten drugi, Awka powinieneś opanować bardzo szybko.

Interpreter AWK można wywołać na kilka sposobów. Krótkie programiki można podawać bezpośrednio jako argument wywołania programu, zaś dane wejściowe podawać na standardowe wejście, co jest użyteczne przy obróbce wyjścia innych komend:

ps aux | awk 'treść programu'

Program można też umieścić w osobnym pliku i ładować opcją -f. Wtedy po podaniu jego nazwy wymieniamy pliki z danymi wejściowymi do obrobienia:

awk -f program.awk dane.txt

AWK traktuje dane wejściowe jako zbiór rekordów oddzielonych separatorem RS. Rekord składa się z kilku pól, między którymi używa się separatora FS. Domyślnie separatorami są znak nowej linii w pierwszym przypadku oraz białe znaki w drugim; można to konfigurować za pom. argumentów wywołania lub ustawiając po uruchomieniu odpowiednie zmienne. Program składa się ze zbioru par wyrażenie - akcja. Interpreter wczytuje kolejny rekord i sprawdza prawdziwość wszystkich wyrażeń. Jeżeli któraś jest prawdziwa, wykonuje przypisaną do niej akcję. Poniżej podaję prosty przykład z wypisaniem nazw wszystkich użytkowników systemu o identyfikatorach między 60, a 90:

# cat /etc/passwd | awk -F: '$3 > 60 && $3 < 90 { print $1 }'

$3 odnosi się do trzeciego pola w rekordzie - dla pliku passwd będzie nim właśnie ID użytkownika. Układamy typowy warunek logiczny i w nawiasach klamrowych definiujemy akcję - wpisywanie loginu zawartego w polu pierwszym. Opcja wywołania -F pozwoliła nam określić separator pól. Można to też było zrobić, ustawiając zmienną FS.

Oto inny przykład zastosowania: suma pamięci RSS zajętej przez wszystkie procesy danego użytkownika:

ps aux | awk 'BEGIN{ sum = 0; } $1 == "zyxist" { sum += $6; } END{ print sum; }'

Tutaj nasz program czyta poszczególne wiersze wyjścia komendy ps wyświetlającej informacje o procesach. Każdy proces jest traktowany jako jeden rekord. Całość składa się z trzech akcji. Pierwsza z nich, BEGIN wykonywana jest przed przeczytaniem pierwszego znaku z pliku wejściowego. Tutaj możemy sobie konfigurować różne rzeczy, które nam się później przydadzą. W naszym przypadku inicjujemy zmienną sum poprzez przypisanie jej wartości 0. Druga z akcji wykona się tylko, gdy w pierwszym polu rekordu będzie odpowiedni identyfikator użytkownika. Wtedy doliczamy wartość jego pamięci RSS do ogólnej puli, którą znajdziemy w szóstym polu. Akcja END wykonuje się na samym końcu. Jej zadaniem jest wypisanie wyniku. Program można uczynić nieco ciekawszym. Jeżeli stanowi on część większego skryptu Basha i jest otoczony odwróconymi apostrofami, pojawiałby się problem, jak umieścić poszukiwaną nazwę użytkownika w treści programu. Można to rozwiązać, podając wartości zmiennych jako argumenty wywołania interpretera. Zmodyfikowana wersja będzie wyglądać tak:

# SUMA=`ps aux | awk 'BEGIN{ sum = 0; } $1 == init_username { sum += $6; } END{ print sum; }' init_username=$USERNAME`

Postanowiłem się przyjrzeć AWK-owi z bardzo prostego powodu. Na studiach miałem przedmiot zwany "Wprowadzeniem do systemu UNIX". Na laboratoriach uczyliśmy się pracy w konsoli polegającej na przetwarzaniu różnych danych systemowymi komendami, a także pisania skryptów Basha. Kto próbował, ten wie, że obróbka niektórych danych kombinacją grepa, heada, cuta, tr-a itd. może czasem przyprawić człowieka o ból głowy. Wśród komend pojawił się też awk, ale w bardzo prymitywnym wykorzystaniu - ot, żeby wypisał np. n-tą kolumnę z danych wejściowych i nic więcej. O języku słyszałem już wcześniej i z ciekawości zajrzałem do manuala. Zobaczywszy składnię, doznałem olśnienia - tak debilnie proste narzędzie było zbawieniem. Później niemal wszystkie możliwe dane kierowałem już do AWK-a :).

Powrót

Komentarze

Napisał Nnn w sobotę, 12 stycznia 2008 o 20:36

Ja to muszę chyba przycisnąć, jak Ty to robisz, że masz na tych studiach czas na blogowanie, przygotowywanie materiałów dla innych etc. Zdradzisz tajemnicę?

Napisał Zyx w sobotę, 12 stycznia 2008 o 22:36

Naturalnie, to żadna tajemnica. Do nauki potrzeba sensownych materiałów. Jeśli takich nie ma, sobie je składam. Opracowując je, jednocześnie się uczę, ponieważ materiał ten w jakiś sposób obrabiam. Gdy skończę, nie widzę powodu, aby inni nie skorzystali na tym i po prostu pakuję to na jakiś FTP. Tłumacząc coś innym, także sam się uczę i utrwalam sobie wiedzę. Podczas nauki trzeba robić sobie przerwy. Napisanie takiego wpisu, jak powyższy, zajmuje 10-15 minut. Podsumowując: wielozadaniowość w czystej postaci :).

Strona 1 z 1 :: 1

Skomentuj

NickInformacja
E-mailTylko do użytku wewnętrznego.
WWWNie zapomnij o http://
LayoutNapisz tu, czy widzisz dzienny czy nocny layout.
WpisFormatowanie wiki
Internauto, pamiętaj! Wolność to nie samowola - dbaj o kulturę wypowiedzi oraz dyskusji w sieci.

Na Zyxist.com panuje swoboda wyrażania opinii oraz krytyki pod dowolnym adresem. Jedyny warunek: musi być ona kulturalna i rzeczowa. Na chamstwo, prostactwo lub jawne obrażanie kogokolwiek nie ma tu miejsca i takie komentarze są bardzo szybko usuwane. Jeśli zamierzasz polemizować z treścią wpisu, wpierw uważnie ją przeczytaj.

© Tomasz "Zyx" Jędrzejewski 2005 - 2009 | Wykonanych zapytań: 2 | Serwer wirtualny zapewnia