Kódím.cz

V této kapitole se vrhneme na pokročilejší zpracování textových souborů.

Řazení řádků a zpracování duplicit

Pro další práci si stáhneme nová pracovní data names.txt.

$ wget https://kodim.cz/cms/assets/devops/uvod-do-linuxu/prikazova-radka/zpracovani-textu/zpracovani-textu/names.txt

Využijme známé příkazy, abychom se s daty seznámili: head, tail, wc -l, cat, less

Řazení příkazem sort

Příkazem sort si můžeme daný seznam jmen seřadit podle abecedy.

$ sort names.txt

Jak dosáhneme seřazení od Z do A? Hledej v manuálu.

Řazení čísel

Pro další ukázku si vygenerujeme soubor deseti čísel pomocí příkazu seq

$ seq 10 > cisla.txt
$ cat cisla.txt
1
2
3
4
5
6
7
8
9
10

Zamícháme si řádky pomocí příkazu shuf.

$ shuf cisla.txt > nahodna_cisla.txt

Obecné textové řazení na číslech bohužel nefunguje, tak jak bychom si přáli

$ sort nahodna_cisla.txt
1
10
2
3
4
5
6
7
8
9

Jakým parametrem dosáhneme toho, aby se čísla seřadila správně? Hledej v manuálu.

uniq

Příkaz uniq slouží k vyřazení duplicitních řádků. Funguje ale pouze, pokud se jedná o duplicitní řádky hned po sobě. Abychom dosáhli požadováného chování, musíme tento filtr aplikovat na seřazený soubor.

Počet jmen

$ sort names.txt | wc -l
100

Počet unikátních jmen

$ sort names.txt | uniq | wc -l
93

Zobrazení duplicitních hodnot

$ sort names.txt | uniq -d
Appleton
Campbell
Dempsey
Kelly
Reynolds
Ulyatt
Webster

Velmi užitečný je u příkazu uniq parametr -c - vytiskne nám počet výskytů daného řádku. Můžeme si pak seznam pomocí tohoto čísla seřadit

$ sort names.txt | uniq -c | sort -n | tail
      1 Widdows
      1 Wilkinson
      1 Willson
      2 Appleton
      2 Campbell
      2 Dempsey
      2 Kelly
      2 Reynolds
      2 Ulyatt
      2 Webster

Nahrazování v textu

Další pracovní soubor fullnames.txt obsahuje jména i příjmení.

$ wget https://kodim.cz/cms/assets/devops/uvod-do-linuxu/prikazova-radka/zpracovani-textu/zpracovani-textu/fullnames.txt

tr

Jednoduchý příkaz tr (translate) slouží k nahrazování znaků z množiny prvního parametru znaky z druhé množiny.

Náhrada mezer za tečky

$ cat fullnames.txt | tr ' ' '.'
Violet.Nielson
Adela.Flynn
Jenna.Turner
Ronald.Trent
Analise.Cooper
Doris.Leigh
Harry.Allen
Marie.Greenwood
Taylor.Murphy
Owen.Vass

Smazání určitých znaků dosáhneme použitím parametru -d následovaným množinou znaků, které chceme smazat (v tomto případě mezera).

$ cat fullnames.txt | tr -d ' '
VioletNielson
AdelaFlynn
JennaTurner
RonaldTrent
AnaliseCooper
DorisLeigh
HarryAllen
MarieGreenwood
TaylorMurphy
OwenVass

Program tr má více užitečných funkcí, např. náhrada všech velkých písmen malými.

$ cat fullnames.txt | tr '[[:upper:]]' '[[:lower:]]'
violet nielson
adela flynn
jenna turner
ronald trent
analise cooper
doris leigh
harry allen
marie greenwood
taylor murphy
owen vass

Nejdůležitější je si uvědomit, že program tr funguje podle jednotlivých znaků. Pro další ukázku si vytvoříme testovací soubor s tímto obsahem:

tým 1
tým 2
tým 3

Jak na to? Napíšeme-li příkaz

$ cat > tymy.txt

program bude čekat na standardní vstup, který přesměruje do souboru tymy.txt. Zkopírujte si text výše a vložte do čekajícího terminálu a zadávání textu ukončete klávesovou zkratkou Ctrl+D.

Pokud budeme nyní chtít čísla týmu změnit na písmena bude fungovat

$ cat tymy.txt | tr '123' 'ABC'
tým A
tým B
tým C

sed

Předchozí příklad použití programu tr je svou funkcionalitou omezen tím, že nahrazuje vždy pouze jeden znak. Co když budeme potřebovat v našich datech nahradit celé slovo jiným slovem? V tom nám pomůže jedna z funkcí pokročilejšího nástroje - programu sed (Stream EDitor).

Program sed využívá něco jako vlastní komplexní jazyk, díky kterému je ovšem i velmi mocný a lze jej využít na spoustu úkolů. My si ukážeme velmi častý příklad, a to využití příkazu s (substitute).

Budeme-li chtít nahradit v datech fullnames.txt mezeru za tečku pomocí sedu, napíšeme:

$ sed 's/ /./' fullnames.txt
Violet.Nielson
Adela.Flynn
Jenna.Turner
Ronald.Trent
Analise.Cooper
Doris.Leigh
Harry.Allen
Marie.Greenwood
Taylor.Murphy
Owen.Vass

První znak je požadovaný příkaz s (substitute), následuje oddělovač lomítko /, potom co chceme najít (mezeru) a za dalším lomítkem napíšeme, na co ji chceme změnit (tečka). Na konci nezapomeneme na uzavírací lomítko.

Lepší příklad bude nahrazení celého slova tým za anglické team

Pozor! Parametr -i příkazu sed přepíše soubor, se kterým pracuje (in-place).

$ sed -i 's/tým/team/' tymy.txt

Řezání sloupců

V této části si povíme něco o zjednoduššení možné práce např. s CSV soubory. Pro ukázku využijeme pracovní data z předchozího cvičení.

Pro vyřezávání sloupců slouží příkaz cut. Pro práci s CSV se nejčastěji využívá v kombinaci s parametry -d (delimiter) udávající oddělovač polí v CSV a -f (field) s číslem pole pro výřez.

$ cut -d ',' -f 1 u202.csv
jméno
Jana Zbořilová
Lukáš Jurčík
Pavel Horák
Lukáš Jurčík
Pavel Kysilka
Kateřina Novotná
Marie Krejcárková
Vasil Lácha
Alexey Opatrný
Petr Valenta
Miroslav Bednář
Pavel Horák
Ivana Dvořáková
Lenka Jarošová
Miroslav Bednář

Využijme pipe a vyextrahujme si dále pouze příjmení studentů

$ cut -d, -f1 u202.csv | cut -d' ' -f2
jméno
Zbořilová
Jurčík
Horák
Jurčík
Kysilka
Novotná
Krejcárková
Lácha
Opatrný
Valenta
Bednář
Horák
Dvořáková
Jarošová
Bednář

Filtrování řádků

Hlavičky CSV souboru se zbavíme pomocí příkazu sed. V jeho jazyce lze použít příkaz d (delete), kterému předchází číslo řádku, které chceme ze vstupu smazat.

$ seq 10 | sed '1d'
2
3
4
5
6
7
8
9
10

Výsledkem této části může být např. seřazený seznam příjmení studentů

$ cut -d, -f1 u202.csv | cut -d' ' -f2 | sed '1d' | sort | uniq
Bednář
Dvořáková
Horák
Jarošová
Jurčík
Krejcárková
Kysilka
Lácha
Novotná
Opatrný
Valenta
Zbořilová

Cvičení