Przetwarzanie plików tekstowych

Komendy omawiane w tej części zajęć: grep, uniq, sort, cut, paste, cat oraz tr

Pipe oraz przekierowanie do pliku

Bardzo ważnym elementem pracy w terminalu Unixowym są strumienie (ang. pipes). Umożliwiają one przekierowanie wyników jednej komendy do drugiej. Owa druga komenda zachowuje się tak, jakby np. wczytała owe dane wejściowe z pliku. Oto prosty przykład oparty na poleceniach z poprzedniej części:

head -20 2gb1.pdb | tail -10
cat  2gb1.pdb | head

Komenda ta drukuje drugie dziesięć linii z pliku 2gb1.pdb. Jak widać, do łączenia komend stosujemy znak |.

Wyniki każdej komendy, który normalnie zostałby wypisany na ekranie, można zapisać do pliku. Nazywamy to przekierowaniem - nazwa chyba dość intuicyjnie oddaje zapis:

head -20 2gb1.pdb > h20

Powyższe polecenie spowoduje utworzenie pliku o nazwie h20. Zaraz potem można zrobić tail h20 , co powinno dać ten sam efekt, co powyższa komenda z pipe. UWAGA: poprzednia zawartość pliku h20 zostanie bezpowrotnie stracona! Aby dopisać do pliku zamiast go nadpisać, używamy >> zamiast >.

Sam plik 2gb1.pdb pobrać można z tej strony.

wc liczy linie, wyrazy i znaki

Komenda wc przydaje się do policzenia linii w wynikach innych komend, np:

ls *.pdb | wc

odpowiada na pytanie, ile plików *.pdb jest w bieżącym katalogu. Podobnie można sprawdzić, ile razy napis “ALA” pojawił się w pliku 16pk.pdb:

grep ALA 16pk.pdb | wc

grep wybiera linie

Komenda grep drukuje na ekranie te linie z pliku (i tylko te), które zawierają podany fragment tekstu. Działanie komendy grep można odwrócić, aby wydrukować te linie, które nie pasują do wzorca (opcja -v).

Zacznijmy od wybrania wszystkich atomów (linii ATOM) z pliku 3dcg.pdb, dostępnego pod tym adresem:

grep ATOM 3dcg.pdb

A może interesują nas tylko atomy węgli alfa? Oznaczone są jako "CA". Każdy aminokwas ma dokładnie jeden taki atom, liczba atomów CA jest równa liczbie aminokwasów w białku.

grep CA 3dcg.pdb | wc

Komenda ta niestety znajdzie też m.in. i taką linię:

REMARK 350 MOLECULE CAN BE GENERATED BY APPLYING BIOMT TRANSFORMATIONS

w której również pojawia się CA (w CAn be generated) Aby zatem mieć pewność, że wybrane zostaną tylko te linie, na których nam zależy, trzeba wybrać linie ATOM z tych linii, które zawierają CA, jak poniżej:

grep CA 3dcg.pdb | grep ATOM

Podobnie możemy wybrać atomy “CA” należący do lizyny (linie zawierające fragment LYS): grep CA 3dcg.pdb | grep LYS

Wyniki (pierwsze pięć linii) wyglądają jak poniżej:

ATOM     92  CA  LYS A  11      32.733  -0.481   8.335  1.00 35.49           C
ATOM    154  CA  LYS A  19      13.453  15.492   4.908  1.00 38.20           C
ATOM    226  CA  LYS A  28      25.964  14.436   0.101  1.00 35.42           C
ATOM    290  CA  LYS A  36      35.348  15.650   4.326  1.00 33.40           C
ATOM    381  CA  LYS A  46      19.769   2.533  -2.803  1.00 40.49           C

Ponieważ fragment “CA” sąsiaduje z “LYS”, można to zrobić jedną komendą:

grep "CA  LYS" 3dcg.pdb | grep ATOM

Należy tylko pamietać o wpisaniu odpowiedniej liczby spacji. Jeżeli wyszukiwany fragment tekstu zawiera spacje, musimy go zawrzeć w cudzysłowiach. Teraz już możemy policzyć, ile aminokwasów zawiera białko 3dcg:

grep CA 3dcg.pdb | grep ATOM | wc

cut wycina kolumny

Komenda cut potrafi wyciąć pionowy fragment z pliku tekstowego. To, co ma być wycięte, można zdefiniować jako kolejne znaki (liczone od lewej od 1, flaga -c) oraz jako pola (flaga -f). Przez pole rozumiemy kolumnę tekstu (np liczb) oddzieloną od innych kolumn separatorem, np znakiem tabulacji albo spacją. Separator definiujemy flagą -d. Poniżej zebrałem kilka przykładów:

  • cut -c 7 plik.txt - wycina siódmy znak z każdej linijki, drukuje kolunmę o szerokości jeden

  • cut -c 1-7 plik.txt - wycina pierwsze siedem znaków z każdej linijki

  • cut -d ',' -f 3 plik.csv - wycina trzecie pole; pola oddzielane są przecinkami (tzw Comma Separated File, CSV)

Ćwiczenie 1: Wytnij nazwy aminokwasów z linii ATOM pliku .pdb

Wynik powinien wyglądać jak poniżej:

ALA
ALA
LYS
LYS

Sortowanie wyników

Plik można posortować komendą sort, zupełnie jak tabelę w Excelu.

  • sort plik.txt - sortuje alfabetycznie linie w pliku

  • sort -f 3 plik.txt - sortuje alfabetycznie linie w pliku wg 3 kolumny

  • sort -f 3 -nr - sortuje numerycznie (bo -n) linie w pliku wg 3 kolumny, wyniki na ekranie pojawiają się w kolejności odwrotnej (bo -r)

Unikalny podzbiór

Polecenie uniq wybiera jedną z wielu identycznych linii, ignoruje zaś pozostałe. Dodanie flagi -c powoduje wydrukowanie liczby identycznych kopii. UWAGA: scalane są jedynie linie następujące po bezpośrednio sobie. Wykonanie komendy uniq -c na wyniku z Ćwiczenia 1 może dać np. następujący wynik:

 8 LEU
 5 ALA
 8 LEU
10 ALA
 8 LEU

Linia LEU pojawia się dwa razy, bo w kolumnie były dwa bloki tych linii, po 8 linii każdy. Aby policzyć ile razy powtórzyła się każda z linii w całym tekście należy linie posortować

Ćwiczenie 2: Ile razy każdy z aminokwasów pojawił się w pliku 3dcg.pdb?

Użyj poznanych już poleceń aby policzyć, ile razy pojawił się każdy z aminokwasów. Pamietaj, że na pojedynczy aminokwas składa się więcej linii tekstu niż jedna. Rozwiązanie tego problemu znajdziesz powyżej. Dodatkowo ułóż wyniki malejąco od najczęściej pojawiającego się aminokwasu. Poniżej pierwsze pięć linii wyników, które powinieneś otrzymać:

43 LEU
32 GLU
32 ALA
28 THR
26 SER

Składanie w całość

Służy do tego komenda paste, która wczytuje kilka plików i skleja je jeden obok drugiego, w kolejnosci od lewej do prawej. Pierwszy wymieniony na liście parametrów plik będzie po lewej, potem drugi, itd. Linie plików oddzielane są separatorem, domyślnie znakiem tabulacji. Separator można zedefiniować flagą -d. W przykładzie poniżej składamy wybrane kolumny pliku w odwrotnej kolejności:

cut -c 1-5 dane.txt > p1
cut -c 10-15 dane.txt > p2
paste -d ' ' p2 p1 > wynik.txt

Jeżeli zajdzie potrzeba sklejenia plików jednego pod drugim, należy skorzystać z komendy cat (od concatenate):

cat plik1.txt plik2.txt

tr podmienia znaki

Z powyższych przykładów widać, że przetwarzanie plików w systemie Unix odbywa się linijka po linijce. Co zrobić, aby przetwarzać wyraz po wyrazie? Czasem najłatwiej jest umieścić wyrazy w oddzielnych liniach, a następnie skorzystać ze znanych już rozwiązań.

Komenta tr zamienia dowolny znak na inny dowolny znak w całym tekście. Polecenie to można wykorzystać do podmiany spacji na znak nowej linii (enter) lub na odwrót:

tr ' ' '\n' < jednalinia.txt > wielelinii.txt
tr ' ' '\n' < wielelinii.txt > jednalinia.txt

Polecenie tr może w jednym przebiegu wykonać kilka podmian, np:

tr 'ABC' 'abc' < wyrazy.txt > wynik.txt

zamieni w całym tekście wielkie litery A, B oraz C na ich małe odpowiedniki. Wielkie litery D itd. nie zostaną podmienione. Zatem jak podmienić wszystkie wielkie na małe? Można oczywiście pracowicie wpisać odpowienie litery, można też skorzystać z predefiniowanych klas znaków:

tr '[:upper:]' '[:lower:]' < wyrazy.txt > wynik.txt

Uwaga: tr nie zamienia wyrazów! Polecenie tr 'Jacek' 'Agata' < plik.txt nie podmieni imion.

Zadanie 1: Jakiego wyrazu J.R.R Tolkien używa najczęściej w swojej książce?

W pliku lort1.txt znajduje się pierwszy tom ,,Władcy Pierścieni’’ - w formacie tekstowym. Policz, ile razy powtarza się każdy z wyrazów. Wydrukuj 20 najczęściej powtarzających się słów. Pamiętaj, aby zamienić wielkie litery na małe, dzięki czemu ,,Then’’ zostanie policzone wspólnie z ,,then’’. Usuń też znaki interpunkcyjne, aby ,,him.’’ było tym samym wyrazem, co ,,him’’