Praca z plikami tekstowymi w linii komend

Praca z plikami tekstowymi w linii komend

Dlaczego to takie ważne?

Jak już wspominałem, praca bioinformatyka to w dużej mierze, o ile nie przede wszystkim praca z plikami tekstowymi. W poprzedniej lekcji pokazałem jak umieścić tekst w pliku przy pomocy operatorów > oraz >> a także jak wyświetlić zawartość pliku używając komend more, less i cat. Linux oferuje jednak znacznie więcej narzędzi pozwalających na efektywną pracę z plikami tekstowymi bez uciekania się do pomocy edytorów tekstu (na które też przyjdzie pora). Poniżej pokażę wybrane możliwości niektórych z nich. Warto jednak samodzielnie poszerzyć wiedzę na ten temat, ponieważ potrafią znacznie usprawnić i przyspieszyć pracę.
W terminalu utwórz katalog Pliki_tekstowe i wejdź do niego. Używając polecenia curl lub wget pobierz plik:
http://ggoralski.pl/files/filogenetyka-data/Orobanchaceae-trnL-trnF-aligned.fasta

Liczenie zawartości i wyświetlanie części pliku - polecenia wc, head, tail.

Wykonaj polecenie:
1
$: wc Orobanchaceae-trnL-trnF-aligned.fasta
2
18 18 9254 Orobanchaceae-trnL-trnF-aligned.fasta
Copied!
Komenda wc wyświetla liczbę linii, słów oraz wielkość liczoną w bajtach podanego pliku. Podając odpowiednie flagi, można uzyskać tylko wybrane dane (sprawdź wc --help), co później wykorzystamy. W przypadku pobranego pliku liczba linii i słów jest taka sama (18) ponieważ w opisach i sekwencjach nie występują spacje a sekwencje zostały umieszczone każda w jednej linii. Sprawdź zatem inny plik:
http://ggoralski.pl/files/filogenetyka-data/Orobanchaceae-trnL-trnF-aligned.aln
Zawiera on dopasowane sekwencje zapisane w formacie CLUSTAL. Zobacz jaka jest zawartość pliku a następnie sprawdź ile ma linii i słów.
Polecenie wc może odczytywać dane z wielu plików jednocześnie:
1
$: wc *
2
233 490 17672 Orobanchaceae-trnL-trnF-aligned.aln
3
18 18 9254 Orobanchaceae-trnL-trnF-aligned.fasta
4
251 508 26926 razem
Copied!
Nie zawsze konieczne jest przeglądanie całego pliku. Czasem chcemy po prostu zobaczyć jak wygląda jego początek i koniec. Wtedy przychodzą nam z pomocą polecenia head i tail, które jak łatwo zgadnąć wyświetlają odpowiednio początek i koniec pliku:
1
$: head Orobanchaceae-trnL-trnF-aligned.aln
2
CLUSTAL 2.1 multiple sequence alignment
3
4
5
KY484464_O._teucrii AGTTATAAC-TTTCAAATTCAGAGAAACCCCGGAATTAAGAGAAA-GGGC
6
KY484493_O._flava AGTGATAAC-TTTCAAATTCAGAGAAACCCCGGAATTAAGAAAAA-GGGC
7
KY484489_O._mayeri AGTGATAAC-TTTCAAATTCAGAGAAACCCCGGAATTAATAAAAA-GGGC
8
KY484471_O._kochii AGTGATAAC-TTTCAAATTCAGAGAAACCCCGGAATTAATAAAAA-GGGC
9
KY484474_O._elatior AGTGATAAC-TTTCAAATTCAGAGAAACCCCGGAATTAATAAAAA-GGGC
10
KU238865_O._coerulescens AGTGATAAC-TTTCAAATTCAGAGAAACCCCGGAATTAAGAAAAA-GGGC
11
KY484502_P._ramosa GGTGATAAC-TTTCAAATTCAGAGAAACTCCGGAATTAATAAAAACGGGC
12
$: tail Orobanchaceae-trnL-trnF-aligned.aln
13
KY484464_O._teucrii AAATG
14
KY484493_O._flava AAATG
15
KY484489_O._mayeri AAATG
16
KY484471_O._kochii AAATG
17
KY484474_O._elatior AAATG
18
KU238865_O._coerulescens GAATG
19
KY484502_P._ramosa GAATG
20
KY484503_P._purpurea GAATG
21
KX524675_Lindenbergia_siniaca GAATG
22
****
Copied!
Liczbę wyświetlanych linii można dostosować używając flagi -n:
1
$: head -n 5 Orobanchaceae-trnL-trnF-aligned.aln
2
CLUSTAL 2.1 multiple sequence alignment
3
4
5
KY484464_O._teucrii AGTTATAAC-TTTCAAATTCAGAGAAACCCCGGAATTAAGAGAAA-GGGC
6
KY484493_O._flava AGTGATAAC-TTTCAAATTCAGAGAAACCCCGGAATTAAGAAAAA-GGGC
7
$: tail -n 5 Orobanchaceae-trnL-trnF-aligned.aln
8
KU238865_O._coerulescens GAATG
9
KY484502_P._ramosa GAATG
10
KY484503_P._purpurea GAATG
11
KX524675_Lindenbergia_siniaca GAATG
12
****
Copied!

grep - wyszukiwanie w pliku tekstowym

Narzędzie grep z pewnością należy do najbardziej użytecznych programów do pracy z plikami tekstowymi. Służy do wynajdywania w plikach danego ciągu znaków.
W katalogu z pobranymi (patrz wyżej) plikami wykonaj polecenie:
1
$: grep Lindenbergia Orobanchaceae-trnL-trnF-aligned.fasta
2
>KX524675_Lindenbergia_siniaca
Copied!
W podanym pliku został znaleziony ciąg znaków Lindenbergia a następnie linia w którym się znajdował została wyświetlona. Jeśli znaleziony fragment nie wyświetla się w innym kolorze niż pozostała część linii to można to uzyskać podając opcję --color=AUTO, np. grep --color=AUTO Lindenbergia Orobanchaceae-trnL-trnF-aligned.fasta.
Można przeszukać od razu wiele plików np. używając znaków wieloznacznych, uzyskamy także informację w jakim pliku znaleziono dopasowanie:
1
$: grep Lindenbergia *
2
3
Orobanchaceae-trnL-trnF-aligned.aln:KX524675_Lindenbergia_siniaca AGTGATAAC-TTTCAAATTCAGAGAAACCCCGGAATTAAAAAAGG-GGGC
4
Orobanchaceae-trnL-trnF-aligned.aln:KX524675_Lindenbergia_siniaca AATCCTGAGCCAAATCCTGT-----TTTCTCAAAACAAA-G--------A
5
Orobanchaceae-trnL-trnF-aligned.aln:KX524675_Lindenbergia_siniaca C-AAAAATAAAGGATAGGTGCAGAGACTCAACGGAAGCTGTTCTAAC---
6
Orobanchaceae-trnL-trnF-aligned.aln:KX524675_Lindenbergia_siniaca -AAATGGAGTTGATTGCGCCGGTAGAGGAATCTTTCCATCGAAACTTCGG
7
Orobanchaceae-trnL-trnF-aligned.aln:KX524675_Lindenbergia_siniaca AAAGGATGAAGGATAAACGTATCTATTGAATACTATATCAAATTATTAAT
8
Orobanchaceae-trnL-trnF-aligned.aln:KX524675_Lindenbergia_siniaca GATATCAAATTATTAATGATGGCCCGAATCTGTATCTGTATTTTT---TA
9
Orobanchaceae-trnL-trnF-aligned.aln:KX524675_Lindenbergia_siniaca ATTTTAATATGAAAAATGGAAAAGTTAGTGTGAATTGATTCCATATTGAA
10
Orobanchaceae-trnL-trnF-aligned.aln:KX524675_Lindenbergia_siniaca GAAAGAATCGAATATTCATT-------CATCAAATCATTCACTCCACAGT
11
Orobanchaceae-trnL-trnF-aligned.aln:KX524675_Lindenbergia_siniaca CCGATAGATC-----TTTTAAAGAATTGATTAATCGGATGAGAATAAAGA
12
Orobanchaceae-trnL-trnF-aligned.aln:KX524675_Lindenbergia_siniaca TAGAGTCCCATTC----------TACATGTCAATACCGGCAACAATGAAA
13
Orobanchaceae-trnL-trnF-aligned.aln:KX524675_Lindenbergia_siniaca TTTATAGTAAGAGGAAAATCCGTCGACTTTAAAAATCGTGAGGGTTCAAG
14
Orobanchaceae-trnL-trnF-aligned.aln:KX524675_Lindenbergia_siniaca TCCCTCTATCCCCAA---AAAAAGTCTATTTTACTTCCA-----------
15
Orobanchaceae-trnL-trnF-aligned.aln:KX524675_Lindenbergia_siniaca -----------AAATATTTAGCCTATTTCA-----------------TTT
16
Orobanchaceae-trnL-trnF-aligned.aln:KX524675_Lindenbergia_siniaca TCG-TTAGCGGTTCCAAATTCCTT--TTCTGATTC--TTTGACA--AACG
17
Orobanchaceae-trnL-trnF-aligned.aln:KX524675_Lindenbergia_siniaca TATTGGGGCGT------------------AAATGACTTT-CTCTTATCAC
18
Orobanchaceae-trnL-trnF-aligned.aln:KX524675_Lindenbergia_siniaca ATGTG------ATATAGAATACACATCCAAATTCAGCAAGGAATTCCTAT
19
Orobanchaceae-trnL-trnF-aligned.aln:KX524675_Lindenbergia_siniaca TTGAATG------ATTCAGAATCAATAACATTACTC-AT-ACTGAAACTT
20
Orobanchaceae-trnL-trnF-aligned.aln:KX524675_Lindenbergia_siniaca AGA---AAGTTCGTCTTTTTGAAGATCCAATAAATTACAGGATTTGGAGA
21
Orobanchaceae-trnL-trnF-aligned.aln:KX524675_Lindenbergia_siniaca AAACTTTGTAATCTTCCCCA--TCCCTTTAATTGACATAGAGCCCAGTC-
22
Orobanchaceae-trnL-trnF-aligned.aln:KX524675_Lindenbergia_siniaca ---ATCTAAT--AAAATCA------GGATGGGAATGGGATTATACATTGG
23
Orobanchaceae-trnL-trnF-aligned.aln:KX524675_Lindenbergia_siniaca GAATG
24
Orobanchaceae-trnL-trnF-aligned.fasta:>KX524675_Lindenbergia_siniaca
Copied!
Jeśli chcemy przeszukać pliki w danym katalogu, należy użyć opcji -r, np.: grep -r Lindenbergia SEKWENCJE.
Narzędzia grep można użyć na przykład do sprawdzenia ile sekwencji znajduje się w pliku fasta. W tym celu należy znaleźć i policzyć linie zawierające znak >. Tu jednak czyha pewna pułapka. Najbardziej oczywistą komendą wydaje się: grep > Orobanchaceae-trnL-trnF-aligned.fasta ale jej wynik będzie taki:
1
$: grep > Orobanchaceae-trnL-trnF-aligned.fasta
2
Składnia: grep [OPCJA]... WZORZEC [PLIK] ...
3
Napisz „grep --help” żeby dowiedzieć się więcej.
Copied!
Po pierwsze polecenie ewidentnie nie zrobiło tego czego po nim oczekiwaliśmy a po drugie jeśli teraz spróbujemy wyświetlić zawartość pliku Orobanchaceae-trnL-trnF-aligned.fasta to okaże się, że jest pusty. Dlaczego?
Przypomnijmy sobie, że operator > służy do przekazania tekstu do pliku. Zatem polecenie grep > Orobanchaceae-trnL-trnF-aligned.fasta uruchomiło polecenie grep (z nieprawidłową składnią) a wynik jego działania zapisało w pliku, w którym chcieliśmy szukać znaków >, wymazując jego poprzednią zawartość. Jest to bardzo łatwy do popełnienia błąd, który może się skończyć utratą wyników pracy! Jak więc należy prawidłowo wyszukać znaku >? Umieszczając go w cudzysłowach:
1
$: grep ">" Orobanchaceae-trnL-trnF-aligned.fasta
2
>KY484464_O._teucrii
3
>KY484493_O._flava
4
>KY484489_O._mayeri
5
>KY484471_O._kochii
6
>KY484474_O._elatior
7
>KU238865_O._coerulescens
8
>KY484502_P._ramosa
9
>KY484503_P._purpurea
10
>KX524675_Lindenbergia_siniaca
Copied!
Zadanie: Zastanów się, co trzeba zrobić, żeby uzyskać nazwy sekwencji w osobnym pliku?
No dobrze, teraz możemy policzyć wyświetlone linie ale wolelibyśmy, żeby komputer sam je policzył. Co prawda istnieje odpowiednia opcja programu grep, która to robi (znajdź ją), ale jest to dobra okazja, żeby pokazać w jaki sposób można połączyć różne polecenia tak aby wykonały razem zadanie.

Potoki, czyli łączymy polecenia.

Chcemy policzyć linie, w których znajduje się znak >. Mamy do dyspozycji jedno narzędzie, które wyszukuje odpowiednie linie (grep) i drugie, które liczy linie (wc). Trzeba je zatem odpowiednio połączyć w jeden ,,taśmociąg''. Wykorzystamy do tego potoki (ang. pipe) - wynik działania grep (strumień) zostanie skierowany do wc. Do łączenia w ten sposób poleceń służy operator |. Polecenia wc użyjemy z flagą -l, która zwraca liczbę linii.
1
$: grep ">" Orobanchaceae-trnL-trnF-aligned.fasta | wc -l
2
9
Copied!
Wiemy, że w pliku mamy 9 sekwencji.
Teraz poznamy kolejną opcję -v, która pozwala ,,odwrócić'' dopasowanie, czyli zwrócić linie, w których nie występuje dopasowanie i połączymy dwa polecenia grep tak, aby uzyskać listę próbek, które nie zawierają ciągu ,,Lindenbergia'':
1
$: grep -v Lindenbergia Orobanchaceae-trnL-trnF-aligned.fasta | grep ">"
2
>KY484464_O._teucrii
3
>KY484493_O._flava
4
>KY484489_O._mayeri
5
>KY484471_O._kochii
6
>KY484474_O._elatior
7
>KU238865_O._coerulescens
8
>KY484502_P._ramosa
9
>KY484503_P._purpurea
Copied!
Jak widać, w drugim wywołaniu plecenia grep nie podaliśmy nazwy pliku, tekst do przeanalizowania został przekazany za pomocą potoku.
Wynik możemy przekazać dalej, na przykład do polecenia sort, które jak nazwa wskazuje sortuje linie tekstu:
1
$: grep -v Lindenbergia Orobanchaceae-trnL-trnF-aligned.fasta | grep ">" | sort
2
>KU238865_O._coerulescens
3
>KY484464_O._teucrii
4
>KY484471_O._kochii
5
>KY484474_O._elatior
6
>KY484489_O._mayeri
7
>KY484493_O._flava
8
>KY484502_P._ramosa
9
>KY484503_P._purpurea
Copied!
Można oczywiście uzyskaną posortowaną listę nazw sekwencji do pliku:
1
$: grep -v Lindenbergia Orobanchaceae-trnL-trnF-aligned.fasta | grep ">" | sort > posortowane.txt
Copied!
Wykonaj powyższe polecenie i sprawdź zawartość pliku posortowane.txt.

xargs - przekazanie argumentów do kolejnego polecenia

Narzędzie xargs pozwala przekazać kolejnemu poleceniu argumenty otrzymane ze standardowego wejścia, czyli np. przez potok. Najłatwiej pokazać to na przykładzie:
1
ls *.fasta | xargs cat > wszystkie.fasta
Copied!
Najpierw mamy polecenie ls *fasta, które zwraca listę plików o przedłużeniu fasta znajdujących się w bieżącym katalogu. Jest ona przekazywana przez potok do polecenia xargs, które przekazuje je poleceniu cat jako kolejne argumenty. Jak wiemy polecenie cat zwraca zawartość pliku, którego nazwa jest argumentem do standardowego wyjścia, którym może być ekran, ale w tym przypadku, przekierowujemy ją do pliku wszystkie.fasta. Tak więc całe polecenie umieszcza zawartość wszystkich plików fasta w pliku wynikowym. W tym przypadku można by było po prostu wykonać komendę:
1
cat *.fasta > wszystkie.fasta
Copied!
ale jak się później przekonamy, nie zawsze tak łatwo jest pominąć xargs i program ten bywa bardzo pożyteczny.

sed - przetwarzanie tekstu

Kolejne bardzo użyteczne narzędzie to sed. Pozwala na edycję strumienia danych. Jedną z zalet używania tego typu programów jest możliwość uzyskiwania i modyfikacji danych z plików bez konieczności ich otwierania od razu w całości, jak to ma miejsce w edytorach tekstu. Nie mam to wielkiego znaczenia w przypadku niewielkich plików ale na przykład pliki uzyskiwane przy sekwencjonowaniu genomów mogą mieć wielkość wielu gigabajtów co w znacznym stopniu utrudnia pracę nad nimi w edytorach tekstu. Nawet jednak dla małych plików praca z linii komend może być po prostu znacznie szybsza.
Prosty schemat użycia sed wygląda tak:
1
sed 's/szukany/zmieniony/g' plik
Copied!
W pliku plik zmieniane są wszystkie ciągi znaków szukany na zmieniony. Bez opcji g (po trzecim ukośniku) zmienione zostanie tylko pierwsze wystąpienie szukanego ciągu w linii. Zamiast pliku można użyć strumienia danych z innych poleceń.
1
$: echo "ATCTTGGATCG" | sed 's/T/U/g'
2
AUCUUGGAUCG
Copied!
Kilka przykładów, wykorzystamy utworzony powyżej plik posortowane.txt, najpierw sprawdźmy co zawiera:
1
$: more posortowane.txt
2
>KU238865_O._coerulescens
3
>KY484464_O._teucrii
4
>KY484471_O._kochii
5
>KY484474_O._elatior
6
>KY484489_O._mayeri
7
>KY484493_O._flava
8
>KY484502_P._ramosa
9
>KY484503_P._purpurea
Copied!
Zamiana znaków '_' na spacje:
1
sed 's/_/ /g' posortowane.txt
2
>KU238865 O. coerulescens
3
>KY484464 O. teucrii
4
>KY484471 O. kochii
5
>KY484474 O. elatior
6
>KY484489 O. mayeri
7
>KY484493 O. flava
8
>KY484502 P. ramosa
9
>KY484503 P. purpurea
Copied!
Usuwane znaku >, ponieważ występuje on tylko raz w linii, opcja g jest zbędna:
1
sed 's/>//' posortowane.txt
2
KU238865_O._coerulescens
3
KY484464_O._teucrii
4
KY484471_O._kochii
5
KY484474_O._elatior
6
KY484489_O._mayeri
7
KY484493_O._flava
8
KY484502_P._ramosa
9
KY484503_P._purpurea
Copied!
Połączmy teraz dwa powyższe i zmieńmy skróty P. oraz O. na pełne nazwy rodzajowe:
1
$: sed 's/>//' posortowane.txt | sed 's/_/ /g' | sed 's/O\./Orobanche/' | sed 's/P\./Phelipanche/'
2
3
KU238865 Orobanche coerulescens
4
KY484464 Orobanche teucrii
5
KY484471 Orobanche kochii
6
KY484474 Orobanche elatior
7
KY484489 Orobanche mayeri
8
KY484493 Orobanche flava
9
KY484502 Phelipanche ramosa
10
KY484503 Phelipanche purpurea
Copied!
Zauważ, że zamiast napisać s/O./Orobanche/ napisałem s/O\./Orobanche/. Co prawda w tym przypadku oba warianty zwrócą taki sam wynik, ale sposób ich działania jest nieco odmienny, o czym za chwilę.
Wynik działania sed często chcemy zapisać w pliku. Można w tym celu użyć znaku >:
1
$: sed 's/>//' posortowane.txt | sed 's/_/ /g' | sed 's/O\./Orobanche/' | sed 's/P\./Phelipanche/' > zmieniony.txt
Copied!
Teraz można wykonać polecenie:
1
$: mv zmieniony.txt posortowane.txt
Copied!
Jeśli chcemy bezpośrednio zmienić plik oryginalny, należy użyć opcji -i ale wtedy nie użyjemy potoków, możemy natomiast zgrupować formuły zmian razem oddzielając je średnikami (jeśli to nie działa spróbuj dodać opcję -e):
1
sed -i 's/>//;s/_/ /g;s/O\./Orobanche/;s/P\./Phelipanche/' posortowane.txt
Copied!
Można też wykonać kolejno operacje:
1
$: sed -i 's/>//' posortowane.txt
2
$: sed -i 's/_/ /g' posortowane.txt
3
$: sed -i 's/O\./Orobanche/' posortowane.txt
4
$: sed -i 's/P\./Phelipanche/' posortowane.txt
Copied!
Należy uważać ze zmianą oryginalnego pliku, lepiej najpierw sprawdzić czy wpisywana formuła edycji działa prawidłowo a dopiero później użyć opcji -i.

Wyrażenia regularne

Wyrażenia regularne są bardzo użyteczne w bioinformatyce, ponieważ są potężnym narzędziem ułatwiającym pracę z plikami tekstowymi i strumieniami tekstu czy ogólniej z ciągami znaków. Dzięki nim można opisać z różnym stopniem ogólności ciągi znaków, czy ich kategorie aby później je wyświetlić, usunąć czy zmodyfikować. Wykorzystuje się je w takich narzędziach jak grep, sed i wielu innych z dobrymi edytorami tekstu włącznie (np. vim).
Przyjrzyjmy się ponownie zmodyfikowanemu plikowi posortowane.txt.
1
$: more posortowane.txt
2
KU238865 Orobanche coerulescens
3
KY484464 Orobanche teucrii
4
KY484471 Orobanche kochii
5
KY484474 Orobanche elatior
6
KY484489 Orobanche mayeri
7
KY484493 Orobanche flava
8
KY484502 Phelipanche ramosa
9
KY484503 Phelipanche purpurea
Copied!
Przypuśćmy, że chcemy uzyskać jedynie listę organizmów, bez numerów GenBank-u. Można by je po kolei usuwać, ale znaczne wygodniej będzie użyć wyrażeń regularnych:
1
$: sed 's/^[[:alnum:]]\+[[:space:]]//' posortowane.txt
2
Orobanche coerulescens
3
Orobanche teucrii
4
Orobanche kochii
5
Orobanche elatior
6
Orobanche mayeri
7
Orobanche flava
8
Phelipanche ramosa
9
Phelipanche purpurea
Copied!
Zanim wyjaśnię jak i dlaczego to działa, trochę teorii.
W wyrażeniach regularnych możemy stosować znaki rozumiane dosłownie (litery, cyfry, spacje, niektóre inne znaki) oraz znaki specjalne ($, *, ., [, \, oraz ^)i wyrażenia, które pozwalają na przykład opisać kategorie znaków, ich liczbę, położenie itp. Na przykład ATG oznacza ciąg ATG ale [ATG] oznacza A lub T lub G. Specjalne znaczenie ma znak \, który zmienia znaczenie następnego znaku - na przykład oznacza, że następujący po nim znak specjalny powinien być rozumiany dosłownie albo, że zwykły znak ma znaczenie specjalne.
W poniższej tabeli znajdują się niektóre przykłady:
Wyrażenie
Znaczenie
Przykład
Znaczenie przykładu
*
zero lub więcej wystąpień wyrażenia
T*
zero lub więcej liter T
\+
jedno lub więcej wystąpień wyrażenia
T\+
jedna lub więcej litera T
\?
zero lub jedno wystąpień wyrażenia
T\?
zero lub jedna litera T
\{i\}
dokładnie i wystąpień wyrażenia
T\{3\}
trzy znaki T
\{i,j\}
pomiędzy i a j wystąpień wyrażenia
T\{3,5\}
pomiędzy 3 a 5 znaków T
\{i,\}
i lub więcej wystąpień wyrażenia
T\{3,\}
przynajmniej 3 znaki T
.
jakikolwiek znak
.\{3\}
trzy dowolne znaki
^
początek linii
^T
znak T występujący na początku linii
$
koniec linii
T$
znak T na końcu linii
[znaki]
jakikolwiek znak z zestawu znaków
[TGA]
T lub G lub A
[x-y]
jakikolwiek znak z zakresu x do y (litery, cyfry)
[A-Z]
duża litera
[a-z 0-9]
mała litera lub cyfra
[^znaki]
jakikolwiek znak z poza zestawu znaków
[^TGA]
jakikolwiek znak oprócz T, G i A
\znak_specjalny
znak specjalny ($, *, ., [, \, ^) rozumiany dosłownie
\^
znak ^ (a nie początek linii)
\(wyrażenie\)
wyrażenie grupujące, dopasowany łańcuch można później wykorzystać, np. wstawiając go w inne miejsce
\n
znak nowej linii
\t
znak tabulatora
[[:alnum:]]
znak alfanumeryczny (litery lub cyfry)
[[:alpha:]]
litera
[[:digit:]]
cyfra
[[:blank:]]
spacja lub tabulator
[[:space:]]
znak odstępu (w tym nowej linii)
Zauważ, że znaczenie znaku ^ zmienia się w zależności od kontekstu - oznacza on początek linii lub negację zakresu znaków.
Wróćmy teraz do pliku posortowane.txt i zastanówmy się jak można opisać numery GenBank-u?
1
$: more posortowane.txt
2
KU238865 Orobanche coerulescens
3
KY484464 Orobanche teucrii
4
KY484471 Orobanche kochii
5
KY484474 Orobanche elatior
6
KY484489 Orobanche mayeri
7
KY484493 Orobanche flava
8
KY484502 Phelipanche ramosa
9
KY484503 Phelipanche purpurea
Copied!
Jest to ciąg znaków zaczynający się na początku linii, zawierający litery i cyfry (znali alfanumeryczne) po którym występuje spacja (jeden ze znaków odstępu).
Teraz poprzednio użyte wyrażenie powinno być bardziej zrozumiałe:
1
$: sed 's/^[[:alnum:]]\+[[:space:]]//' posortowane.txt
Copied!
^ początek linii [[:alnum:]]\+ jeden lub więcej znaków alfanumerycznych [[:space:]] znak odstępu.
Zadanie: Spróbuj usunąć numery GenBank-u używając innego wyrażenia.
Po przejrzeniu powyższej tabeli powinno być jasne, dlaczego powyżej zamiast napisać s/O./Orobanche/ napisałem s/O\./Orobanche/. Kropka oznacza jakikolwiek znak, ponieważ także oznacza kropkę oba wyrażenia zadziałają w tym przypadku (!) tak samo, ale jeśli chcemy być pewni, że dopasujemy znak ., to powinniśmy użyć przed niem znaku \, co spowoduje, że znak zostanie odczytany dosłownie.
Zamieszczone w tabeli wyrażenie \(wyrażenie\) zapewne wydaje się niejasne. Pokażę zatem na przykładzie jak może być wykorzystane. Tym razem zadaniem będzie przeniesienie numeru GenBank-u na koniec linii. Można to zrobić tak:
1
$: sed 's/^\([[:alnum:]]\+[[:space:]]\)\(.*\)/\2 \1/' posortowane.txt
2
Orobanche coerulescens KU238865
3
Orobanche teucrii KY484464
4
Orobanche kochii KY484471
5
Orobanche elatior KY484474
6
Orobanche mayeri KY484489
7
Orobanche flava KY484493
8
Phelipanche ramosa KY484502
9
Phelipanche purpurea KY484503
Copied!
Powyżej wykorzystałem dwa wyrażenia grupujące. Pierwszy z nich obejmuje dopasowanie numeru GenBank-u (oraz spację), drugie pozostałą część tekstu (.* oznacza zero lub więcej dowolnych znaków. Po drugim ukośniku odwołuję się do wcześniej znalezionych dopasowań: \1 oznacza pierwsze dopasowanie, \2 drugie dopasowanie. Umieszczając je w kolejności \2 \1 umieściłem pierwsze dopasowanie po drugim.
Zamianę można ograniczyć do linii, w których znajduje się inne dopasowanie. Na przykład:
1
$: sed "/^>/ s/A/0/g" plik.fasta
Copied!
Zamieni znaki A na 0 w liniach, które zaczynają się od >.
Z kolei polecenie:
1
$: sed "/^>/! s/A/0/g" plik.fasta
Copied!
Dokona zamiany w liniach, które nie rozpoczynają się od >.
Jeśli przed s w poleceniu umieścimy liczbę, będzie się ono odnosiło do linii w pliku o podanym numerze. Możemy np. w ten sposób dodać tekst w pierwszej linii w pliku plik.txt:
1
sed -i "1s/^/Tytuł dzieła\n/" plik.txt
Copied!
Aby usunąć linie, w których znajduje się dany wzorzec stosujemy następującą komendę:
1
sed '/wzorzec/d' plik
Copied!
Na przykład poniższa komenda usunie wszystkie linie z opisami sekwencji z pliku sekwencje.fasta
1
sed -i '/^>/d' sekwencje.fasta
Copied!

tr - zmiana i usuwanie znaków

Program tr ma podobne zastosowanie do sed-a, specjalizuje się jednak w zamianie pojedynczych znaków.
Używamy go w ten sposób:
1
tr opcje znaki1 znaki2
Copied!
znaki1 - to zestaw znaków które zmieniamy znaki2 - to zestaw znaków na które zmieniamy
Pokażę to na kilku przykładach.
Zamiana * na -
1
$: echo "AGGC*TT" | tr "*" "-"
2
3
AGGC-TT
Copied!
Usunięcie znaków -. Tak można łatwo usunąć z sekwencji znaki oznaczające indele.
1
$: echo "AG--GC-TT" | tr -d "-"
2
3
AGGCTT
Copied!
Zamiana A na T, C na G, G na C oraz T na A.
1
$: echo "AGGCTT" | tr "ACGT" "TGCA"
2
3
TCCGAA
Copied!
W ten sposób można otrzymać łatwo sekwencję komplementarną. Zauważ, że powyższa komenda nie zmienia sekwencji ACGT na TGCA, ale podmienia poszczególne znaki.
tr nie ma możliwości bezpośredniej modyfikacji pliku, dlatego jeśli chcemy zmienić plik, użyjemy znaków przekierowania < do pliku wejściowego i > dla pliku wyjściowego.
Utwórz plik sekwencje.txt o zawartości:
1
CGACCAGATTACGGGGCCCATTA
2
CGAGACATTTATATACGATATAG
3
AAATTTCGCGCGCAGATAGCATA
Copied!
Teraz utworzymy dla tych krótkich sekwencji sekwencje komplementarne:
1
tr "ACGT" "TGCA" < sekwencje.txt > sekwencje_komplementarne.txt
Copied!
albo
1
cat sekwencje.txt | tr "ACGT" "TGCA" > sekwencje_komplementarne.txt
Copied!
Otrzymujemy plik sekwencje_komplementarne.txt:
1
GCTGGTCTAATGCCCCGGGTAAT
2
GCTCTGTAAATATATGCTATATC
3
TTTAAAGCGCGCGTCTATCGTAT
Copied!
Teraz połączmy te sekwencje w jedną, długą. W tym celu usuniemy \n oznaczający znak nowej linii.
1
tr -d "\n" < sekwencje_komplementarne.txt > polaczona_sekwencja_komplementarna.txt
Copied!
Tu też oczywiście można też użyć komendy cat i znaku |:
1
cat sekwencje_komplementarne.txt| tr -d "\n" > polaczona_sekwencja_komplementarna.txt
Copied!
Plik wynikowy, zgodnie z założeniem, posiada jedną długą sekwencję:
1
GCTGGTCTAATGCCCCGGGTAATGCTCTGTAAATATATGCTATATCTTTAAAGCGCGCGTCTATCGTAT
Copied!

rev - odwracanie łańcucha znaków

Bardzo prostym, ale użytecznym narzędziem jest rev (od reverse), który odwraca łańcuch znaków.
1
$: echo "ACGTTT" | rev
2
3
TTTGCA
Copied!
Teraz można sekwencję w pliku polaczona_sekwencja_komplementarna.txt także odwrócić. W efekcie otrzymamy sekwencję komplementarną, odwróconą.
1
cat polaczona_sekwencja_komplementarna.txt | rev > polaczona_sekwencja_komplementarna_odwrocona.txt
Copied!
Cały proces łączenia przekształcania sekwencji w odwróconą i komplementarną można zmieścić w ,,jednolinijkowcu'' używając potoków i przekierowania:
1
cat sekwencja.txt | tr "ACGT" "TGCA" | tr -d "\n" | rev > sekwencja_RC.txt
Copied!

uniq - usuwanie powtórzeń

Polecenie uniq pozwala na usuwanie powtarzających się linii. Na przykład chcielibyśmy otrzymać listę rodzajów z taksonów znajdujących się w pliku fasta ale tak, aby każda nazwa występowała tylko raz.
Pobierz plik:
1
http://ggoralski.pl/files/filogenetyka-data/atp6-samples.fasta
Copied!
Najpierw uzyskajmy opisy sekwencji:
1
$: grep ">" atp6-samples.fasta
2
>KY492922.1 Dendropicos elliotii isolate DA07 ATP6 (ATP6) gene, partial cds; mitochondrial
3
>KY492921.1 Dendropicos stierlingi isolate ZMUC74329 ATP6 (ATP6) gene, complete cds; mitochondrial
4
>KY492920.1 Dendropicos poecilolaemus isolate ZMUC72915 ATP6 (ATP6) gene, complete cds; mitochondrial
5
>KY492919.1 Campethera punctuligera isolate ZMUC56174 ATP6 (ATP6) gene, complete cds; mitochondrial
6
>KY492918.1 Campethera cailliautii isolate ZMUC56172 ATP6 (ATP6) gene, complete cds; mitochondrial
7
>KY492917.1 Dendropicos fuscescens isolate Z34 ATP6 (ATP6) gene, complete cds; mitochondrial
8
>KY492916.1 Campethera cailliautii isolate W45 ATP6 (ATP6) gene, complete cds; mitochondrial
9
>KY492915.1 Chloropicus xantholophus isolate MNHN2005922 ATP6 (ATP6) gene, complete cds; mitochondrial
10
....
Copied!
Jak widać opisy są nieco bardziej złożone niż w poprzednio używanym pliku, ponadto jest ich więcej (powyżej widać tylko początek listy).
Teraz trzeba wyodrębnić nazwy rodzajowe. W naszym pliku jest to drugi ciąg znaków alfanumerycznych. Zastanów się jak go uzyskać?
1
$: grep ">" atp6-samples.fasta | sed 's/\(^>[[:alnum:]]\+\.[[:digit:]][[:space:]]\)\([[:alnum:]]\+\)\([[:space:]].\+\)/\2/'
2
Dendropicos
3
Dendropicos
4
Dendropicos
5
Campethera
6
Campethera
7
Dendropicos
8
Campethera
9
Chloropicus
10
Campethera
11
Dendropicos
12
...
Copied!
Tym razem wykorzystałem trzy wyrażenia grupujące: pierwszy oznacza numer GenBank-u (znali alfanumeryczne, kropka, cyfra) ze spacją, drugi znajduje ciąg znaków alfanumerycznych odpowiadających nazwie rodzajowej a trzeci grupuje pozostałe znaki w linii. Jak widać wykorzystujemy w dalszej części polecenia tylko drugie dopasowanie co powoduje, że zwracana jest tylko nazwa rodzajowa. Szkopuł w tym, że nazwy te wyświetlają się wielokrotnie, a chcielibyśmy mieć listę rodzajów, taką w której każda występowałaby tylko raz. Dodajmy zatem polecenie uniq:
1
$: grep ">" atp6-samples.fasta | sed 's/\(^>[[:alnum:]]\+\.[[:digit:]][[:space:]]\)\([[:alnum:]]\+\)\([[:space:]].\+\)/\2/' | uniq
2
Dendropicos
3
Campethera
4
Dendropicos
5
Campethera
6
Chloropicus
7
Campethera
8
Dendropicos
9
Campethera
10
Ipophilus
11
...
Copied!
Efekt jest nie do końca zgodny z oczekiwaniami. Co prawda duplikaty zostały usunięte, ale tylko wtedy gdy znajdowały się bezpośrednio po sobie. Tak właśnie działa uniq. Wykorzystajmy zatem polecenie, które sortuje linie, czyli sort wtedy wszystkie takie same linie znajdą się bezpośrednio przy sobie.
1
$: grep ">" atp6-samples.fasta | sed 's/\(^>[[:alnum:]]\+\.[[:digit:]][[:space:]]\)\([[:alnum:]]\+\)\([[:space:]].\+\)/\2/' | sort | uniq
2
Campethera
3
Chloropicus
4
Cooperia
5
Dendropicos
6
Ipophilus
7
Paracoccidioides
8
Pocillopora
Copied!
Zadanie: policz ile sekwencji i ile różnych nazw rodzajowych znajduje się w pliku