TEXTUTILS(1)

NAZWA
textutils - opis pakietu narzędzi tekstowych GNU

OD TŁUMACZA
Podręczniki man dla narzędzi tekstowych GNU nie są już rozwijane. Niniejsza strona podręcznika powstała jako tłumaczenie, używanej przez twórców jako podstawowej, dokumentacji formatu info. W pliku, który czytasz umieszczono część dokumentacji dotyczącą wspólnych cech i opcji programów oraz informacje, które z różnych przyczyn nie znalazły się na stronach opisujących poszczególne polecenia pakietu. Szczegółowe opisy samych poleceń znajdziesz we właściwych, osobnych stronach podręcznika.

WSTĘP
Niniejszy podręcznik opisuje zestaw narzędzi tekstowych GNU w wersji 2.0. Jak i inne podręczniki pakietu, i ten nie jest wyczerpujący: nie usiłowano wyjaśnić podstawowych pojęć w sposób odpowiedni dla nowicjuszy. Zatem, jeśli jesteś zainteresowany, włącz się, proszę, w udoskonalanie go. Skorzysta na tym cała wspólnota GNU. Narzędzia tekstowe GNU są w większości zgodne ze standardem POSIX.2. Błędy proszę zgłaszać, w jęz.angielskim, do <bug-fileutils@gnu.org>. Pamiętaj, by zamieścić numer wersji, architekturę maszyny, pliki wejściowe i inne informacje potrzebne do powielenia błędu: wprowadzane znaki, czego się spodziewałeś, co otrzymałeś i dlaczego jest to źle. Pliki diff są mile widziane, ale proszę dołączyć również opis problemu, gdyż czasem ciężko jest wyciągnąć wnioski. Podręcznik ten powstał pierwotnie na bazie uniksowych stron man napisanych przez Davida MacKenzie i aktualizowanych przez Jima Meyeringa. Autorytatywną dokumentacją jest obecnie dokumentacja w formacie info; strony man nie są już rozwijane i aktualizowane. Franc,ois Pinard wykonał wstępną konwersję do formatu Texinfo. Karl Berry wykonał indeksy, trochę reorganizacji i edycji wyników. Richard Stallman wniósł swój zwykły nieoceniony wgląd w całość procesu.

ZAWARTOŚĆ PAKIETU
Obecnie pakiet narzędzi tekstowych GNU zawiera dwadzieścia kilka programów:

  Wypisywanie całości plików
    cat         łączenie i wypisywanie plików
    tac         łączenie i wypisywanie odwróconych plików
    nl          numerowanie linii i wypisywanie plików
    od          wypisywanie plików w formacie ósemkowym i innych

  Formatowanie zawartości plików
    fmt         reformatowanie akapitów tekstu
    pr          stronicowanie i kolumnowanie plików do wydruku
    fold        zawijanie linii wejściowych do zadanej szerokości

  Wypisywanie części plików
    head        wypisywanie początku plików
    tail        wypisywanie końcówki plików
    split       podział pliku na części stałej wielkości
    csplit      podział pliku na części zależne od kontekstu

  Podsumowywanie plików
    wc          wypisywanie liczby bajtów, słów i linii
    sum         wypisywanie sumy kontrolnej i liczby bloków
    csum        wypisywanie sumy CRC liczby bloków
    md5sum      wypisywanie lub sprawdzanie skrótu danych

  Sortowanie i działania na plikach posortowanych
    sort        sortowanie plików tekstowych
    uniq        pozostawianie unikalnych linii w pliku
    comm        porównywanie dwu posortowanych plików liniami
    ptx         tworzenie indeksu permutacyjnego zawartości pliku
    tsort       sortowanie topologiczne

  Działania na polach wewnątrz linii
    cut         wypisywanie wybranych części linii
    paste       zlepianie linii plików
    join        łączenie linii według wspólnego pola

  Działania na znakach
    tr          zamiana, ściskanie, usuwanie znaków
    expand      zamiana tabulacji na spacje
    unexpand    zamiana spacji na tabulacje

OPCJE WSPÓLNE
Pewne opcje dostępne są we wszystkich opisywanych programach (naprawdę powinien je przyjmować każdy z programów GNU).

--help
    Wyświetla informację o stosowaniu programu i listę wszystkich dostępnych opcji, pomyślnie kończy pracę.

--version
    Wyświetla numer wersji programu i pomyślnie kończy pracę.

Otwarcie skrzynki narzędziowej z programami
Ten rozdział pierwotnie pojawił się w 'Linux Journal', volume 1, nr 2, na kolumnie `What's GNU?'. Został napisany przez Arnolda Robbinsa.

  Wprowadzenie
W tym miesiącu artykuł jest tylko ubocznie związany z Projektem GNU, gdyż opisuje kilka narzędzi GNU obecnych w systemie Linux i sposoby, na jakie możesz z nich korzystać. Faktycznie artykuł jest o filozofii "Narzędzi programowych" w rozwijaniu i wykorzystywaniu programów. Filozofia narzędzi programowych była ważnym i integralnym pojęciem w początkowym projekcie i rozwoju Uniksa (którego Linux i GNU są zasadniczo klonami). Niestety, przy współczesnym nacisku intersieci i błyskotliwych GUI, wydaje się, że idea ta spadła na pobocze. To wstyd, ponieważ zapewnia ona potężny model myślowy do rozwiązywania wielu rodzajów problemów. Sporo ludzi nosi w kieszeniach spodni szwajcarski scyzoryk. Scyzoryk jest wygodnym narzędziem: ma kilka ostrzy, śrubokręt, pincetę, wykałaczkę, zestaw gwoździ, korkociąg i może kilka innych rzeczy. Do codziennych drobnych, różnorodnych zadań, gdzie potrzebujesz prostego narzędzia ogólnego zastosowania, jest właśnie tym, o co chodzi. Z drugiej strony, doświadczony cieśla nie buduje domu scyzorykiem. Zamiast tego ma skrzynkę wypchaną specjalizowanymi narzędziami -- jest tam piła, młotek, śrubokręt, strug i tak dalej. I dokładnie wie kiedy i gdzie użyć każdego z narzędzi. Nie przyłapałbyś go na wbijaniu gwoździ rękojeścią śrubokrętu. Konstruktorzy Uniksa w Bell Labs byli całkiem zawodowymi programistami i wyszkolonymi naukowcami komputerowymi. Zauważyli, że choć rozwiązanie wszystko-w-jednym może przyciągać użytkownika, gdyż ma on tylko jeden program do korzystania, w praktyce programy takie są a. trudne do napisania, b. trudne w konserwacji i usuwaniu błędów, oraz c. trudne do rozbudowy, przystosowania do nowych sytuacji. Uważali, że zamiast tego, programy powinny być specjalizowanymi narzędziami. Krótko mówiąc, każdy program "powinien robić jedną rzecz dobrze". Nie więcej i nie mniej. Takie programy są łatwiejsze do zaprojektowania, napisania i zrozumienia -- robią tylko jedną rzecz. Ponadto zauważyli, że przy odpowiednim mechanizmie łączenia programów całość jest większa od sumy składowych. Wiążąc kilka specjalizowanych programów możesz zrealizować konkretne zadanie, do którego żaden z nich nie był projektowany i osiągnąć to dużo szybciej i łatwiej niż pisząc dla niego specjalizowany program. W dalszej części artykułu zobaczymy kilka (klasycznych) tego przykładów. Ważnym dodatkowym punktem było to, że jeśli jest to niezbędne, należy najpierw zrobić narzędzia, które będą potrzebne, jeżeli nie ma się jeszcze odpowiednich w skrzynce narzędziowej.

  Przekierowanie wejścia/wyjścia
Mam nadzieję, że jesteś obeznany z podstawami przekierowywania wejścia/wyjścia w powłoce, w szczególności z pojęciami "standardowego wejścia", "standardowego wyjścia" i "standardowego wyjścia błędów (diagnostycznego)". Zwięźle: "standardowe wejście" jest źródłem danych, skąd pochodzą dane. Program nie musi wiedzieć ani dbać o to, czy źródłem danych jest plik dyskowy, klawiatura, taśma magnetyczna czy nawet czytnik kart perforowanych. Podobnie, "standardowe wyjście" jest odpływem danych, dokąd dane spływają. Program nie powinien ani wiedzieć ani dbać o to, gdzie to może być. Programy, które tylko czytają swoje standardowe wejście, robią coś z tymi danymi i wysyłają je na standardowe wyjście, nazywane są "filtrami", przez analogię do filtrów w wodociągach. W powłoce uniksowej bardzo łatwo jest zestawić potoki danych: [tłum.: ang.'pipeline' to 'rurociąg' lub, w informatyce, 'potok']
    program_tworzacy_dane | filtr1 | .... | filtrN > koncowe.dane
Zaczynamy od utworzenia surowych danych pierwotnych. Każdy z filtrów stosuje pewne kolejne przekształcenie danych, aż wychodząc z potoku będą one mieć pożądaną postać. To jest eleganckie i dobre dla standardowego wejścia i standardowego wyjścia. A gdzie się tu pojawia standardowe wyjście błędów? Cóż, pomyślmy o 'filtr1' w powyższym potoku. Co się stanie, jeśli napotka on błąd w przyjmowanych danych? Jeżeli wypisze komunikat o błędzie na standardowe wyjście, to po prostu zniknie on w potoku wejścia do 'filtr2' a użytkownik zapewne nigdy go nie zobaczy. Zatem programiści potrzebują miejsca, gdzie mogliby wysyłać komunikaty o błędach, tak by użytkownik je zauważył. Jest to standardowe wyjście diagnostyczne i zwykle związane jest z twoją konsolą lub oknem, nawet jeśli przekierowałeś standardowe wyjście programu gdzieś poza ekran. Aby programy filtrujące mogły współdziałać, musi zostać uzgodniony format danych. Najprostszym i najłatwiejszym w wykorzystaniu formatem są zwykłe wiersze tekstu. Uniksowe pliki danych są zazwyczaj po prostu strumieniami bajtów, o wierszach zakończonych znakiem LF ASCII (Line Feed - wysuw linii), konwencjonalnie w literaturze dotyczącej Uniksa nazywanym "znakiem nowej linii" (newline). (Jest to '\n' jeśli programujesz w C.) To format stosowany przez wszystkie tradycyjne programy filtrujące. (Wiele wcześniejszych systemów operacyjnych wypracowało środki i specjalizowane programy do obsługi danych binarnych. Unix zawsze wystrzegał się takich rzeczy, zgodnie z filozofią, że najłatwiej jest móc przeglądać i modyfikować dane po prostu edytorem tekstu.) Dobrze, starczy wprowadzenia. Przyjrzyjmy się niektórym narzędziom, a wtedy zobaczymy jak wiązać je ze sobą na ciekawe sposoby. W dalszych rozważaniach pokażemy tylko te opcje wiersza poleceń, które nas interesują. Tak jak zawsze powinieneś, dwukrotnie sprawdź dokumentację systemową. Znajdziesz tam pełne opisy.

  Polecenie 'who'
Pierwszym programem jest polecenie 'who'. Samodzielne, tworzy listę aktualnie zalogowanych użytkowników. Mimo, że piszę to w systemie jednoużytkownikowym, będziemy udawać, że zalogowanych jest kilka osób:
     $ who
     arnold   console Jan 22 19:57
     miriam   ttyp0   Jan 23 14:19(:0.0)
     bill     ttyp1   Jan 21 09:32(:0.0)
     arnold   ttyp2   Jan 23 20:48(:0.0)
Znak '$' jest tu zwyczajową zachętą powłoki, po której napisałem 'who'. Zalogowane są trzy osoby, w tym ja dwukrotnie. W tradycyjnych systemach Unix nazwy użytkowników nigdy nie mają więcej niż osiem znaków. Ta mała ciekawostka przyda się później. Wyjście z 'who' wygląda ładnie, ale dane nie są aż tak pasjonujące.

  Polecenie 'cut'
Następnym programem, któremu się przyglądniemy jest polecenie 'cut' (wytnij). Wycina ono kolumny lub pola z danych wejściowych. Na przykład, możemy nakazać mu wypisanie tylko nazwy zgłoszeniowej i nazwiska z pliku /etc/passwd. Plik posiada siedem pól, rozdzielonych dwukropkami:
     arnold:xyzzy:2076:10:Arnold D. Robbins:/home/arnold:/bin/ksh
Do pobrania pierwszego i piątego pola, użylibyśmy takiego wycinania:
     $ cut -d: -f1,5 /etc/passwd
     root:Operator
     ...
     arnold:Arnold D. Robbins
     miriam:Miriam A. Robbins
     ...
Z opcją '-c', 'cut' wycina konkretne znaki (tj. kolumny) wierszy wejściowych. To polecenie wygląda na przydatne do filtrowania danych.

  Polecenie 'sort'
Następnie przyjrzymy się 'sort'. To jedno z najpotężniejszych poleceń w systemie typu uniksowego. Często będziesz go używał przy konstruowaniu różnych wymyślnych rurociągów. 'sort' czyta i sortuje każdy z podanych w wierszu poleceń plików. Następnie scala uporządkowane dane i wypisuje na standardowe wyjście. Jeśli w wierszu poleceń nie poda się żadnych nazw plików to czyta standardowe wejście (w ten sposób robimy zeń filtr). Sortowanie oparte jest na leksykograficznym porządku znaków lub kryteriach porządkowania zadanych przez użytkownika.

  Polecenie `uniq'
Na koniec (przynajmniej na razie), przyglądniemy się programowi 'uniq'. Przy sortowaniu danych często uzyskasz powtórzone wiersze, wiersze, które są identyczne. Zazwyczaj potrzebujesz tylko jednego wystąpienia każdego z nich. Tu właśnie pojawia się 'uniq'. Czyta on ze swego standardowego wejścia, spodziewając się, że jest ono posortowane. Wypisuje tylko jeden egzemplarz każdego zduplikowanego wiersza. 'uniq' ma kilka opcji. W dalszym ciągu wykorzystamy opcję '-c', wypisującą przed niepowtarzalnym wierszem ile razy wystąpił on w danych wejściowych.

  Łączenie narzędzi
Załóżmy teraz, że mamy system BBS z zalogowanymi dziesiątkami użytkowników. Zarządzający chcą, by operator systemu (SysOp) napisał program tworzący posortowaną listę zalogowanych użytkowników. Co więcej, nawet jeśli użytkownik jest zalogowany wielokrotnie, jego nazwa powinna w wyniku pojawić się tylko raz. SysOp mógłby siąść z dokumentacją systemową i napisać program w C, który by to robił. Kosztowałoby to pewnie kilkaset linii kodu i około dwu godzin pisania, testowania i usuwania błędów. Jednak, znając narzędzia programowe, SysOp może zamiast tego zacząć od utworzenia tylko listy zalogowanych użytkowników:
     $ who | cut -c1-8
     arnold
     miriam
     bill
     arnold
Następnie, posortować listę:
     $ who | cut -c1-8 | sort
     arnold
     arnold
     bill
     miriam
Na koniec, przepuścić posortowaną listę przez 'uniq', by wypielić duplikaty:
     $ who | cut -c1-8 | sort | uniq
     arnold
     bill
     miriam
Polecenie 'sort' faktycznie posiada opcję '-u', która robi to, co 'uniq'. Jednak 'uniq' ma inne zastosowania, w których nie można go zastąpić przez 'sort -u'. SysOp umieszcza ten potok w skrypcie powłoki i udostępnia go wszystkim użytkownikom systemu:
     # cat > /usr/local/bin/listusers
     who | cut -c1-8 | sort | uniq
     ^D
     # chmod +x /usr/local/bin/listusers
Warto tu zauważyć cztery zalety. Po pierwsze, przy pomocy zaledwie czterech programów, w jednej linii poleceń, SysOp mógł oszczędzić około dwu godzin pracy. Co więcej, potok powłoki jest prawie tak samo wydajny, jak byłby program w C, a o wiele bardziej efektywny jeśli chodzi o czas programisty. Czas ludzki jest o wiele kosztowniejszy niż czas komputera, a w naszym współczesnym społeczeństwie, gdzie "nigdy nie ma dość czasu by wszystko zrobić", zaoszczędzenie dwu godzin czasu programisty jest nie byle jakim wyczynem. Po drugie, równie istotne jest podkreślenie, że przy pomocy _połączenia_ narzędzi możliwe jest wykonanie specyficznego zadania, nigdy nie przewidywanego przez autorów pojedynczych programów. Po trzecie, wartościowe jest też stopniowe budowanie potoku, jak to zrobiliśmy. Pozwala ono na przyglądnięcie się danym na każdym etapie przebiegu potoku, co pomaga uzyskać pewność, że rzeczywiście poprawnie używasz narzędzi. Na koniec, dzięki zapakowaniu potoku w skrypt powłoki, inni użytkownicy mogą korzystać z twojego polecenia, nie musząc pamiętać o zawartości tego wymyślnego opakowania. Z punktu widzenia sposobu uruchamiania, skrypty powłoki i skompilowane programy są nierozróżnialne. Po uprzedniej rozgrzewce, przypatrzymy się dwu kolejnym, bardziej skomplikowanym potokom. Potrzebujemy dla nich wprowadzić jeszcze dwa narzędzia. Pierwszym jest polecenie 'tr', oznaczające "transliterację". Polecenie 'tr' wymienia znaki, działając na zasadzie znak-na-znak. Zwykle stosowane jest do takich rzeczy jak odwzorowanie dużych liter na małe.
     $ echo ThIs ExAmPlE HaS MIXED case! | tr '[A-Z]' '[a-z]'
     this example has mixed case!
Interesuje nas kilka opcji:

-c  działa na dopełnieniu wskazanych znaków, tj. działania odnoszą się do znaków spoza zadanego zestawu

-d  usuwa z wyniku znaki określone w pierwszym zestawie

-s  ściska w wyniku powtórzone znaki w pojedynczy znak.

Za chwilę będziemy korzystać ze wszystkich trzech opcji. Innym poleceniem, któremu się przyjrzymy jest 'comm'. Pobiera ono dwa posortowane pliki jako dane wejściowe i wypisuje ich wiersze w trzech kolumnach. Kolumny wynikowe są unikalnymi wierszami z pierwszego pliku, unikalnymi wierszami z drugiego pliku i wierszami danych wspólnymi dla obu. Opcje '1', '-2' i '3' pomijają odpowiednie kolumny. Nie jest to intuicyjne i wymaga pewnego przywyknięcia. Na przykład:
     $ cat f1
     11111
     22222
     33333
     44444
     $ cat f2
     00000
     22222
     33333
     55555
     $ comm f1 f2
             00000
     11111
                     22222
                     33333
     44444
             55555
Pojedyncza kreska jako nazwa pliku nakazuje 'comm' czytanie standardowego wejścia zamiast zwykłego pliku. Jesteśmy teraz gotowi do skonstruowania wymyślnego potoku. Pierwszym zastosowaniem jest licznik częstości słów. Pomaga autorowi stwierdzić, czy nie nadużywa on pewnych słów. Pierwszym krokiem jest zmiana wielkości wszystkich liter z pliku wejściowego na jedną wielkość. "to" i "To" przy zliczaniu są tym samym słowem.
     $ tr '[A-Z]' '[a-z]' < whats.gnu | ...
[tłum.: zauważ, że dla języka polskiego, podobnie jak w następnym kroku, należy uwzględnić dodatkowo nasze znaki diakrytyczne. Można dołączyć je do podanego zakresu lub, lepiej, posłużyć się klasą znaków i ustawieniami narodowymi - zobacz tr(1).]
Następnym krokiem jest pozbycie się znaków przestankowych. Słowa cytowane i niecytowane powinny być traktowane identycznie; najłatwiej będzie po prostu wyrzucić zawadzającą interpunkcję.
     $ tr '[A-Z]' '[a-z]' < whats.gnu | tr -cd '[A-Za-z0-9_  12]' | ...
Drugie polecenie 'tr' działa na dopełnieniu podanych znaków, którymi są litery, cyfry, podkreślenie i odstęp. ' 12' oznacza znak nowej linii, należy go pozostawić. Dla dobrego pomiaru w działającym skrypcie powinien być też zawarty znak tabulacji (ASCII tab). Na tym etapie, mamy dane składające się ze słów rozdzielonych odstępami. Słowa zawierają wyłącznie znaki alfanumeryczne i znak podkreślenia. Następnym krokiem jest rozbicie danych na części tak, byśmy mieli po jednym słowie w wierszu. Jak wkrótce zobaczymy, znacznie ułatwia to zliczanie.
     $ tr '[A-Z]' '[a-z]' < whats.gnu | tr -cd '[A-Za-z0-9_  12]' |
     > tr -s '[ ]' ' 12' | ...
To polecenie zamienia odstępy w znaki nowej linii. Opcja '-s' ściska wielokrotne znaki nowej linii wyniku w pojedynczy. Pomaga nam to uniknąć pustych wierszy. (Znak '>' jest tu wtórnym znakiem zachęty powłoki. Powłoka wypisuje go, gdy zauważy, że nie zakończyłeś wpisywania całego polecenia.) Teraz mamy dane składające się z jednego słowa w każdym wierszu, bez znaków interpunkcyjnych, wszystkie pisane jedną wielkością. Jesteśmy gotowi do zliczania każdego z nich:
     $ tr '[A-Z]' '[a-z]' < whats.gnu | tr -cd '[A-Za-z0-9_  12]' |
     > tr -s '[ ]' ' 12' | sort | uniq -c | ...
Na tym etapie, dane mogą wyglądać jakoś tak:
       60 a
        2 able
        6 about
        1 above
        2 accomplish
        1 acquire
        1 actually
        2 additional
Wynik jest posortowany według słów, nie według liczby wystąpień! Chcielibyśmy natomiast mieć jako pierwsze najczęściej używane słowa. Na szczęście, łatwo to osiągnąć przy pomocy dwu dodatkowych opcji 'sort':

-n  wykonuje sortowanie liczbowe, a nie tekstowe

-r  odwraca kolejność sortowania

Ostateczny potok wygląda tak:
     $ tr '[A-Z]' '[a-z]' < whats.gnu | tr -cd '[A-Za-z0-9_  12]' |
     > tr -s '[ ]' ' 12' | sort | uniq -c | sort -nr
      156 the
       60 a
       58 to
       51 of
       51 and
      ...
No, no! Sporo do opowiadania. Nadal jednak obowiązują te same zasady. Przy pomocy sześciu poleceń, w dwu wierszach (faktycznie jednej długiej linii podzielonej dla wygody), stworzyliśmy program, który robi coś ciekawego i pożytecznego, w dużo krótszym czasie niż moglibyśmy napisać program w C robiący to samo. Niewielkie zmiany w powyższym potoku mogą nam dać prosty korektor pisowni! Do stwierdzenia, czy napisałeś poprawnie jakieś słowo wystarczy, że poszukasz go w słowniku. Jeśli w nim nie występuje, to możliwe, że twoja pisownia jest nieprawidłowa. Tak więc, potrzebujemy słownika. Jeżeli masz dystrybucję Slackware Linux, to plik '/usr/lib/ispell/ispell.words' jest posortowanym, zawierającym 38.400 słów, słownikiem. Zatem, jak porównać nasz plik ze słownikiem? Jak poprzednio, utworzymy posortowaną listę słów, po jednym w wierszu:
     $ tr '[A-Z]' '[a-z]' < whats.gnu | tr -cd '[A-Za-z0-9_  12]' |
     > tr -s '[ ]' ' 12' | sort -u | ...
Teraz potrzebujemy tylko listy słów, których NIE MA w słowniku. Tu właśnie pojawia się polecenie 'comm'.
     $ tr '[A-Z]' '[a-z]' < whats.gnu | tr -cd '[A-Za-z0-9_  12]' |
     > tr -s '[ ]' ' 12' | sort -u |
     > comm -23 - /usr/lib/ispell/ispell.words
Opcje '-2' i '-3' likwidują wiersze występujące tylko słowniku (drugi plik), i występujące w obu plikach. Wiersze obecne tylko w pierwszym pliku (standardowe wejście, nasz strumień słów), są słowami, których nie ma w słowniku. Są to prawdopodobne błędy pisowni. Taki potok był pierwszym etapem budowy korektora pisowni w Uniksie. Istnieje jeszcze kilka innych narzędzi wymagających krótkiej wzmianki.

grep
    szuka w plikach tekstu pasującego do wyrażenia regularnego

egrep
    jak 'grep', ale z bardziej rozbudowanymi wyrażeniami regularnymi

wc  zlicza wiersze, słowa, znaki

tee kopiuje dane do plików i na standardowe wyjście; działa jak T-kształtka w rurociągu danych

sed edytor strumieniowy, zaawansowane narzędzie

awk język manipulacji danymi, kolejne zaawansowane narzędzie

Filozofia narzędzi programowych daje też następującą radę: "Niech ktoś inny zrobi trudną część pracy". To znaczy, weź coś, co zaspokoi większość twoich potrzeb, a następnie przekształcaj dalej, aż uzyskasz pożądaną postać. Podsumowując:

1.  Każdy program powinien robić jedną rzecz, ale dobrze. Nie więcej, nie mniej.

2.  Łączenie programów w odpowiedni sposób prowadzi do rezultatu, gdzie całość jest większa od sumy części. Prowadzi też do nowatorskich zastosowań programów, których ich autorzy nawet sobie nie wyobrażali.

3.  Programy nigdy nie powinny wypisywać dodatkowych danych nagłówkowych czy kończących, gdyż mogłyby one zostać przesłane potokiem. (Cecha, o której wcześniej nie wspominaliśmy).

4.  Niech ktoś inny wykona trudną część roboty.

5.  Znaj swoje narzędzia! Każdego programu używaj we właściwy sposób. Jeżeli nie masz odpowiedniego narzędzia - zrób je.

W chwili powstania tego artykułu, wszystkie omawiane programy były dostępne przez anonimowe ftp z prep.ai.mit.edu jako /pub/gnu/textutils-1.9.tar.gz. Wersja 1.9 była wówczas bieżącą. Sprawdź w najbliższym archiwum GNU jaka wersja jest aktualnie bieżąca. Główną siedzibą archiwum jest obecnie ftp.gnu.org. Nic z tego, co przedstawiłem w tym artykule nie jest nowe. Filozofia Narzędzi Programowych została po raz pierwszy wprowadzona w książce 'Software Tools', Briana Kernighana i P.J. Plaugera (Addison-Wesley, ISBN 0-201-03669-X). Książka ta pokazywała jak pisać i wykorzystywać narzędzia programowe. Została napisana w 1976, korzystając z preprocesora FORTRAN-u o nazwie 'ratfor' (RATional FORtran). Wówczas C nie był tak wszechobecny jak dziś. FORTRAN był. Ostatni rozdział przedstawiał 'ratfor' dla procesora FORTRAN-u, napisany w 'ratforze'. 'ratfor' wygląda bardzo podobnie do C -- jeśli znasz C, nie będziesz mieć żadnych kłopotów ze zrozumieniem kodu. W 1981 książka ta została zaktualizowana i udostępniona jako 'Software Tools in Pascal' (Addison-Wesley, ISBN 0-201-10342-7). Obie książki są nadal drukowane i są rzeczywiście warte przeczytania jeśli jesteś programistą. Z pewnością bardzo zmieniły mój punkt widzenia na programowanie. Początkowo programy z obu książek były dostępne (na 9-calowej taśmie) z Addison-Wesley. Niestety, już tak nie jest, mimo że możesz znaleźć kopie rozproszone w Internecie. Przez wiele lat działała Software Tools Users Group - Grupa Użytkowników Narzędzi Programowych, której członkowie przenieśli pierwotne programy 'ratforu' na niemal każdy system komputerowy z kompilatorem FORTRAN-u. Popularność grupy zanikła w połowie lat 80-tych, gdy Unix zaczął rozpowszechniać się poza uniwersytetami. Przy obecnym rozmnożeniu kodu GNU i innych klonów programów uniksowych, programom tym poświęca się teraz niewiele uwagi. Współczesne wersje C są o wiele wydajniejsze i robią więcej niż te programy. Niemniej jednak, książki te są niezrównane jako opis dobrego stylu programowania, głosząc wciąż cenną filozofię. Gorąco je polecam. Podziękowania: chciałbym wyrazić swą wdzięczność Brianowi Kernighanowi z Bell Labs, pierwszemu Kowalowi Narzędzi Programowych, za przejrzenie tego artykułu.

ZOBACZ TAKŻE

cat(1)
    łączenie i wypisywanie plików

comm(1)
    porównywanie dwu posortowanych plików liniami

csplit(1)
    podział pliku na części zależne od kontekstu

csum(1)
    wypisywanie sumy CRC liczby bloków

cut(1)
    wypisywanie wybranych części linii

expand(1)
    zamiana tabulacji na spacje

fmt(1)
    reformatowanie akapitów tekstu

fold(1)
    zawijanie linii wejściowych do zadanej szerokości

head(1)
    wypisywanie początku plików

join(1)
    łączenie linii według wspólnego pola

md5sum(1)
    wypisywanie lub sprawdzanie skrótu danych

nl(1)
    numerowanie linii i wypisywanie plików

od(1)
    wypisywanie plików w formacie ósemkowym i innych

paste(1)
    zlepianie linii plików

pr(1)
    stronicowanie i kolumnowanie plików do wydruku

ptx(1)
    tworzenie indeksu permutacyjnego zawartości pliku

sort(1)
    sortowanie plików tekstowych

split(1)
    podział pliku na części stałej wielkości

sum(1)
    wypisywanie sumy kontrolnej i liczby bloków

tac(1)
    łączenie i wypisywanie odwróconych plików

tail(1)
    wypisywanie końcówki plików

tr(1)
    zamiana, ściskanie, usuwanie znaków

tsort(1)
    sortowanie topologiczne

unexpand(1)
    zamiana spacji na tabulacje

uniq(1)
    pozostawianie unikalnych linii w pliku

wc(1)
    wypisywanie liczby bajtów, słów i linii