csplit:podział pliku na podstawie zawartości
cut:wybranie kolumn
join:połączenie plików wg wspólnej kolumny
paste:sklejenie plików kolumnami
shuf:mieszanie kolejności linii w pliku
split:podział pliku na równe kawałki
tac:wypisanie pliku liniami od tyłu
tr:zamiana znaków
uniq:wybranie linii powtarzających się
poniedziałek, 16 lutego 2009
Skrzynka z narzędziami
Jednolinijkowce w AWK-u
AWK jest językiem programowania nadającym się wybitnie do tworzenia jednolinijkowców. "Jednolinijkowiec" to skrypt napisany ad-hoc, bez edytora, od razu w linii komend. Często mieści się w jednej linii - stąd nazwa.
Pracując nad analizą techniczną kursów walut używam często awk-a i bash-a jako narzędzi szybkiego prototypowania i błyskawicznych kalkulacji.
Przykład: w pliku A.txt mam dane w postaci tekstowej, każda linijka zawiera jedną liczbę - wartość kursu w danym punkcie. Chcę obliczyć średnią wykładniczą z dziesięciu okresów.
Za pomocą jednolinijkowca w AWK-u robię to tak:
awk '{s=0.1*$1+0.9*s; print s}' A.txt
Po przeczytaniu tego artykułu też będziesz to umieć.
Przykład innego typu: Chcę z pliku B.txt wybrać co dziesiątą linię:
awk '{n++; if(n>=10) {print; n=0}}' B.txt
Przykład trzeci - powiedzmy, że w pliku C.txt mam dwie kolumny z wartościami liczbowymi. Chcę obliczyć średnią wartość liczb w obu kolumnach. Posługuję się więc jednolinijkowcem, który tworzę w locie:
awk '{p+=$1; x+=$2; n++} END {print p/n, x/n}' C.txt
I tak dalej, wszysto szybko, łatwo i bezbłędnie.
AWK jest genialnie dostosowany do takich celów - ma kilka konstrukcji składniowych, kilka funkcji i kilka reguł, które trzeba poznać, podręcznik mieści się w jednym manualu systemowym, a możliwości są ogromne. Nie ma obiektów, klas, wyjątków ani modułów, ale robi to, co potrzebne. Aby sobie to uzmysłowić, wystarczy zrozumieć, jak działa AWK.
DZIAŁANIE AWK-a
Program w AWK-u to lista reguł. Każda reguła to wzorzec i akcja. Program czyta dane rekord po rekordzie, znajduje pierwszy wzorzec, który może być dopasowany do rekordu i wykonuje skojarzoną z nim akcję. Rekord dzieli się na pola, oznaczane w akcjach i wzorcach symbolami $1, $2, $3 itd.
Przykład:
awk '$1>1 {n++} END {print n}'
awk - to komenda - nazwa programu awk '$1>1 {n++} END {print n}' - to program w AWK-u, składa się z dwóch reguł: $1>1 {n++} - wzorzec $1>1 oznacza rekordy, w których wartość numeryczna pierwszego pola jest większa niż 1, akcja {n++} oznacza inkrementację zmiennej n END {print n} - wzorzec END to sztuczny wzorzec, nie dopasowywany do żadnego rekordu, skojarzona z nim akcja wykonywana jest na zakończenie programu. W tym wypadku wypisuje liczbę n.
Powyższy program liczy linie, w których pierwsza kolumna zawiera liczbę większą od 1, a następnie wypisuje wynik.
Akcje ujęte są w nawiasy {}, warunki to wyrażenia relacyjne lub specjalne symbole BEGIN lub END.
Inny przykład - pomnożenie wszystkich liczb zawartych w pliku:
awk 'BEGIN {x=1} {x*=$1} END {print x}'
Aby zmusić program do zainicjowania zmiennej jedynką został tu użyty wzorzec BEGIN. Tyle informacji wystarczy, aby rozpocząć eksperymentowanie.
środa, 1 października 2008
Post Scriptum i PostScript
if (x[1] > 2*y)
x[1]=y-1;
else
x[1] += 1;
zapisane w PostScripcie wygląda na przykład tak:
x 1 get 2 y mul gt{
x 1 y 1 sub put
}
{
x 1 x 1 get 1 add put
} ifelse
Na tym poziomie da się to jeszcze czytać przy odrobinie wprawy, ale już widzimy różnicę - musimy się trochę skupić. W bardziej złożonych programach wyszukanie błędu jest mozolne i naprawdę można tego uniknąć używając Post Scriptum.
Taka beznawiasowa składnia nazywana jest postfiksową - tak nazywa się zapis, w którym argumenty stoją przed operatorami - stąd chyba zresztą wzięła się nazwa PostScriptu. Autor Post Scriptum celnie zauważył, że składnia ta jest jedynym elementem języka, który powstrzymuje programistów od masowego bezpośredniego używania PostScriptu. Pozostałe elementy języka, takie jak zarządzanie pamięcią, system typów, czy wreszczie rozbudowany system graficzny, stanowiący clue PostScriptu, są wygodne, przemyślane i dopracowane - można powiedzieć, że aż chciałoby się ich używać, gdyby nie ten język ...
Wniosek był jeden: trzeba stworzyć język, który będzie miał klasyczną składnię, a tłumaczony będzie na PostScript. Tak powstało Post Scriptum. Podobnie powstał język C - w wyniku znużenia zawiłościami kodu assemblerowego. Ale można w C zakodować prawie wszystko to, co w asemblerze. Podobnie w naszym nowym języku - program w Post Scriptum może być funkcjonalnie równoważny dowolnemu programowi w PostScripcie.
Nowy język posiada klasyczne konstrukcje sterujące: pętle, instrukcje "if", funkcje. Obsługuje typy danych PostScriptu: słowniki (odpowiedniki paskalowych rekordów, struktur C, czy PHP-owych hashów), stringi i oczywiście liczby stało- i zmiennoprzecinkowe. Operatory PostScriptu udokumentowane bardzo dokładnie w "PostScript Language Reference Manual" firmy Adobe) są wywoływane bezpośrednio jak każda inna funkcja, dzięki czemu Post Scriptum daje dostęp do całej
graficznej maszynerii PostScriptu. Możliwe jest też włączanie kodu napisanego w PostScripcie bezpośrednio do programu w Post Scriptum.
Na etapie kompilacji można dołączać fragmenty kodu (klasyczna dyrektywa "include") jak i gotowe fragmenty PostScriptu (dyrektywa "import").
Autor poprzedził pracę nad tym językiem poszukiwaniami gotowego rozwiązania tego typu i - o dziwo - nie znalazł. W dalszych planach, o ile mi wiadomo, jest wsparcie dla kontroli typów (obecnie język jest polimorficzny, jak PostScript), kontrola prototypów funkcji i inne feature'y wspierające szybkie tworzenie i debugowanie kodu.
Życzę autorowi dalszego zapału i zachęcam wszystkich do odwiedzenia strony "Post Scriptum".
czwartek, 19 czerwca 2008
Najprostsze pliki graficzne
Wszystkie trzy oparte są na wspólnej zasadzie: plik zawiera nagłówek z koniecznymi danymi (rozmar, typ) i prostokątną macierz pixeli. Pixel określa kolor w postaci składowych RGB (dla pixmap PPM), stopień szarości (dla greymap) lub jednobitową wartość biało-czarną (dla bitmap). Format zdefiniowano w wariancie binarnym i tekstowym. W przyrodzie występują z rozszerzeniem .ppm, .pbm i .pgm, ale także .pnm (Portable aNyMap).
Dalszym rozwinięciem tego formatu jest PAM, występujący tylko w formie binarnej, pozwalający na dalsze rozszerzenia, kanał alfa itp.
W Twoim Unixie znajdziesz mnóstwo programów - narzędzi zawierających w nazwie ciąg znaków ppm, pnm, pgm itp. Oto rezultat komendy "apropos pnm" na komputerze, na którym piszę ten artykuł (pierwszy fragment) :
anytopnm (1) - attempt to convert an unknown type of image file to a portable anymap bmptopnm (1) - convert a BMP file into a portable anymap calibrate_ppa (8) - pnm2ppa calibration tool fiascotopnm (1) - Convert compressed FIASCO image to PGM, or PPM fitstopnm (1) - convert a FITS file into a portable anymap gemtopnm (1) - convert a GEM .img file into a portable anymap giftopnm (1) - convert a GIF file into a portable anymap jpegtopnm (1) - convert JPEG/JFIF file to portable pixmap or graymap palmtopnm (1) - convert a Palm pixmap into a portable anymap pamdeinterlace (1) - remove ever other row from a PAM/PNM image pamfile (1) - describe a Netpbm (PAM or PNM) file pamstretch (1) - scale up a PNM or PAM image by interpolating between pixels.......
pamstretch-gen (1) - use pamstretch and pnmscale to scale by non-integer values pngtopnm (1) - convert a Portable Network Graphics file into portable anymap pnm2ppa (1) - convert portable anymap (PNM) images to HP's
PPA printer format. pnmalias (1) - antialias a portable anyumap. pnmarith (1) - perform arithmetic on two portable anymaps pnmcat (1) - concatenate portable anymaps pnmcolormap (1) - create quantization color map for a portable anymap pnmcomp (1) - composite (overlay) two portable anymap files together pnmconvol (1) - general MxN convolution on a portable anymap pnmcrop (1) - crop a portable anymap pnmcut (1) - cut a rectangle out of a portable anymap pnmdepth (1) - change the maxval in a portable anymap pnmenlarge (1) - read a portable anymap and enlarge it N times pnmfile (1) - describe a portable anymap pnmflip (1) - perform one or more flip operations on a portable anymap pnmgamma (1) - perform gamma correction on a portable anymap pnmhisteq (1) - histogram equalise a portable anymap pnmhistmap (1) - draw a histogram for a PGM or PPM file pnmindex (1) - build a visual index of a bunch of anymaps pnminterp (1) - scale up a PNM or PAM image by interpolating between pixels pnminterp-gen (1) - use pamstretch and pnmscale to scale by non-integer values pnminvert (1) - invert a portable anymap pnmmargin (1) - add a border to a portable anymap pnmmontage (1) - create a montage of portable anymaps pnmnlfilt (1) - non-linear filters: smooth, alpha trim mean, optimal estimation smoothing, edge enhancement.
Biorąc pod uwagę, że każdy taki plik można zamienić na postać tekstową, którą łatwo przetwarzać przy użyciu narzędzi typu awk/perl/bash/sed, mamy w ręce pełną bibliotekę graficzną ...
poniedziałek, 16 czerwca 2008
OOA/OOD i Air Traffic Control
W książce Coada i Yourdona autorzy posługują się przykładem wziętym z życia: systemem kontroli ruchu powietrznego. Pełno tam tras, radarów i samolotów. Kiedy to czytałem, nie wiedziałem, dlaczego akurat te radary są takie ważne. Potem, parę lat później, przypadkowo natrafiłem na klasyczną unixową grę tekstową atc.
Był to prosty symulator konsoli radaru kontrolera ruchu powietrznego. Na ekranie powyżej widzimy, jak to działa. Właśnie w mój obszar wleciały dwa samoloty: b7 i A7. A7 zmierza w stronę wyjścia E1, a b7 w stronę E4 (widzimy ten "plan lotu" w tabelce po prawej). Oba znajdują się na wysokości 7 tys. stóp (oznacza to siódemka w symbolu samolotu). Należy, wydając odpowiednie komendy dotyczące kierunku ruchu i wysokości lotu doprowadzić wszystkie samoloty do ich przeznaczenia i nie dopuścić do zderzenia. Po kilkunastu minutach konsola radaru zawiera kilka lub kilkanaście samolotów, a człowiek jest znużony z powodu ciągłego napięcia.
Ponieważ sterowanie wyimaginowanymi samolotami jest bardzo zajmujące, postarałem się o zdobycie bardziej rozbudowanych, graficznych programów, w końcu zacząłem używać darmowego symulatora firmy Xavius. Prawdę mówiąc ze wszystkich gier komputerowych, jakie miałem w życiu poznać (cóż poznałem ich niewiele w porównaniu z moimi kolegami) ten rodzaj wciągnął mnie najbardziej. I siedząc godzinami w najwyższym napięciu nad sektorem powietrznym Chicago lub Los Angeles powoli uzyskiwałem wgląd w hierarchię klas Coada i Yourdona dotyczącą dziedziny ruchu powietrznego. Jedno jest pewne: aby zobaczyć te klasy, trzeba choć trochę poznać tematykę, której dotyczy dany projekt.
Prymitywna gra atc(6) okazała się bardzo zbliżona w charakterze do tych złożonych. Najwidoczniej jej autor wykonał kawał dobrej analizy obiektowej ...
czwartek, 5 czerwca 2008
Widzenie barwne i Unix
Znalazłem gdzieś w sieci obrazek mający przedstawiać widmo światła białego:
Postanowiłem zbadać, jak został skonstruowany z trzech barw
składowych. Tęcza powinna składać się z barw prostych o zmieniającej się płynnie długości. Grafika komputerowa to - wiadomo - mieszanina trzech barw prostych o różnym natężeniu w różnych punktach - coś całkiem innego niż oryginalny pierwowzór. Gdyby istniała istota zdolna do widzenia absolutnego barw, bez trudu rozpoznałaby oszustwo. Ja potrzebowałem do tego kilku narzędzi uniksowych.
Po pierwsze rozkompresowałem obrazek przy użyciu djpeg:
$ djpeg pasek.jpg > pasek.ppm
Następnie przekonwertowałem plik na format tekstowego ppm'a, aby łatwiej mi było go dalej przetwarzać:
$ pnmnoraw pasek.ppm > pasek.txtSzybki rzut oka do pliku:
$ head pasek.txt P3 600 66 255 254 0 0 254 0 0 254 0 0 254 0 0 253 1 0....
Mamy 600 pikseli szerokości.
Teraz zamieniam trochę porządek, żeby mieć jeden piksel w jednym wierszu:
$ awk '{
> S="";
> for (i=1; i<=NF; i++) {
> S=S" "$i;
> if (i % 3 == 0) {
> print S;
> S="";
> }
> }
> }' pasek.txt > pasek.x
$ head pasek.x
254 0 0
254 0 0
254 0 0
254 0 0
.... Dobrze idzie, teraz wezmę jeden rządek i narysuję wykres nasycenia trzech barw:
$ head -n 600 pasek.x > pasek3 $ gnuplot gnuplot> plot 'pasek3' using 1 with lines, 'pasek3' using 2 with
lines, 'pasek3' using 3 with lines
Pięknie, widać, co zrobił autor tego rysunku: wygenerował go automatycznie używając kawałków liniowych funkcji !Jeszcze tylko wykonałem zrzut ekranu i zamieniłem go na jpg, żeby umieścić wykres w blogu:
$ xwd $ xwdtopnm pasek.xwd > pasek3.ppm xwdtopnm: writing PPM file $ cjpeg pasek3.ppm > wykres1.jpgGotowe.
Ciekawe, jakbym to zrobił w Windowsach ...
Ciekawostką jest fakt, że gnuplot do oznaczania kolejnych linii używa kolorów właśnie w kolejności
czerwony, zielony, niebieski.
Inną ciekawostką jest czerwony składnik po prawej stronie widma -
tam, gdzie mamy mocny fiolet.
piątek, 6 lipca 2007
TargetWriter
# the template hello.tpl:
cat <<END_OF_FILE
<html>
<head>
<title> $(target MAIN_TITLE) </title>
</head>
<body>
<h1> $(target MAIN_TITLE) <h1>
$(target TEXT)
</body>
</html>
END_OF_FILE
# the text file:
. ./hello.tpl
write MAIN_TITLE H E L L O
write TEXT Hello world !