Hlavní navigace

Hrátky z řádky: porovnání souborů a číselné řady

Petr Macek

Další díl občasného zpravodajství z příkazové řádky. Dnes se podíváme na několik programů pro porovnávání souborů, jejich spojování a vygenerujeme si i nějakou číselnou řadu.

Porovnávání souborů

Když se řekne porovnávání souborů (budeme pracovat převážně s textovými), mnoho uživatelů asi hned napadne program diff. Je to šikovný program, ale každému se nemusí líbit jeho výstup. A občas to může být zbytečně velký kanon na vrabce. Ukážeme si několik méně známých programů, které dělají stejnou nebo podobnou práci.

Napřed si připravíme dva testovací soubory:

$ cat prvni.txt
ahoj,
ja jsem prvni soubor a jsem
jediny a originalni
$ cat druhy.txt
ahoj,
ja jsem druhy soubor a jsem
skoro jediny a originalni

Cmp

Cmp porovnává dva soubory bajt po bajtu a oznámí první rozdíl. Pokud přidáme parametr -b, řekne i o který znak se jedná.

$ cmp prvni.txt druhy.txt
prvni.txt druhy.txt se liší: bajt 15, řádek 2
$ cmp -b prvni.txt druhy.txt
prvni.txt druhy.txt se liší: bajt 15, řádek 2 je 160 p 144 d

Sdiff

Program sdiff má více ukecaný a přehlednější výstup. Každý ze souborů zobrazuje na jedné polovině obrazovky a zvýrazňuje rozdíly. Soubor prvni.txt si rozšíříme o jeden řádek:

echo koncim >> prvni.txt

Parametr -s říká, že se nebudou vypisovat shodné řádky, dalšími parametry je možné nastavit ignorování více mezer, bílé znaky na konci řádků apod.

$ sdiff -s prvni.txt druhy.txt
ja jsem prvni soubor a jsem                                   | ja jsem druhy soubor a jsem
jediny a originalni                                           | skoro jediny a originalni
                                  > koncim

Znak | značí řádek, kde je rozdíl, <> pak značí řádek chybějící v jednom nebo druhém souboru. Sdiff toho umí ale mnohem více, třeba interaktivní spojování souborů. Koukněte do manuálu.

Comm

Dalším porovnávačem je program comm. Porovnává řádek po řádku a záleží na pořadí řádků v souborech. Zobrazení výstupu řeší jinak, a to pomocí tabelátoru.

  • bez – řádek je v pouze v prvním souboru
  • 1 tab – řádek je v druhém souboru
  • 2 taby – řádek je shodný v obou souborech
$ comm prvni.txt druhy.txt
                ahoj,
        ja jsem druhy soubor a jsem
ja jsem prvni soubor a jsem
jediny a originalni
koncim
        skoro jediny a originalni

Diff

Příkaz diff je o dost mocnější. Parametrem -i říkáme, aby nerozlišoval velká a malá písmena, pro textové soubory se mohou hodit i parametry týkající se bílých znaků na koncích řádků ( -Z), množství mezer mezi slovy ( -b)…

Více se o něm dozvíte třeba v blogu Petra Krčmáře.

Číselné řady s Jot

Teď trochu něco jiného. Začnu programem jot. Nazval bych jej generátorem číselných a znakových řad. Nemusí se jednat jen o sekvenční data, jot umí generovat i pomocí náhody.

Základní parametry jsou čtyři – počet hodnot, první, poslední a krok. Pokud chceme nějaký vynechat, zadáváme místo něj pomlčku.

V některých případech nemusíme ani to. Sílu tohoto programu si nejlépe ukážeme na pár příkladech.

Začneme s čísly:

$ jot 4
1
2
3
4

Teď sestupně. Všimněte si, že se k číslu –9 vůbec nedostaneme, protože dříve nastane počet opakování (8). Pokud by byl počet opakování vyšší, výstup se zastaví u hodnoty –9.

$ jot -p1 8 0 -9 -0.5
0.0
-0.5
-1.0
-1.5
-2.0
-2.5
-3.0
-3.5

Parametr -p není nutné zapisovat ani takto, zkuste třeba následující příklad. Krok se automaticky dopočítá a počet desetinných míst se taky upraví:

$ jot  5 0 10.00

Občas se taková věc může hodit třeba v kombinaci s for:

for hodnota in `jot 4 100`
do
    echo $hodnota
done

A jdeme na znaky. Neznáte pozici písmene H v ascii tabulce?

$ jot 1 H
72

Můžeme převádět i obráceně:

$ jot -c 1 72
H

Je možné pracovat i s řetězci

$ jot -w ahoj_%c 26 a
ahoj_a
ahoj_b
ahoj_c
ahoj_d
ahoj_e
ahoj_f
…

Generování jednoduchých hesel: -s říká, jaký oddělovač použít, -r je náhoda a -c říká, že jde o znaky. Pak už jen počet opakování, minimální a maximální hodnota.

$ jot -s "" -r -c 8 a z
hdwimmst

Expand a unexpand

Tato utilita nám v zadaném souboru nahradí tabulátory mezerami nebo obráceně.

$ expand pokus_s_taby.txt > pokus_s_mezerami.txt

Obráceně to dělá utilita unxepand, nezapomeňte na parametr  -a.

$ unexpand -a pokus_s_mezerami.txt > pokus_s_taby.txt

Paste

Paste spojuje soubory, vezme první řádky všech souborů a dá je na první řádek, stejně tak s ostatními.

Vytvoříme si dva ukázkové soubory

$ cat prvni.txt
ahoj,
ja jsem prvni soubor,
kde jsou
4 radky

$ cat druhy.txt
nazdar,
ja jsem tvuj
druhy kolega
a stejne dlouhy

$ paste prvni.txt druhy.txt
ahoj,   nazdar,
ja jsem prvni soubor,   ja jsem tvuj
kde jsou        druhy kolega
4 radky a stejne dlouhy

Paste toho umí taky ještě víc. Když chcete třeba nahradit konce řádků znakem tab

$ paste -s prvni.txt
ahoj,   ja jsem prvni soubor,   kde jsou        4 radky

Podobnou funkci mí i příkaz lam. Ten se třeba v základní instalaci Ubuntu nevyskytuje, ale ve FreeBSD je.

Vynechání sloupců s colrm

Nedávno jsem v diskuzi narazil na extrahování některých sloupců z výpisu. Většina uživatelů na to využívá třeba awk. Existuje ale i utilita colrm, která je velmi jednoduchá a dáváte jí pouze jeden nebo dva parametry – od a do kterého sloupce má vynechávat.

$ ls -al | colrm 10 33
…
drwx----- čen 14  2013 .adobe
-rw------ srp  2 22:38 .bash_history
-rw-r--r- čen 14  2013 .bash_logout
-rw-r--r- čen 14  2013 .bashrc
…

Tak to je pro dnešek vše. Hrátky z řádky asi začnou znovu a nepravidelně vycházet. Máte nějaké tipy? Prosím, podělte se v diskuzi.

Našli jste v článku chybu?
4. 8. 2016 10:57
BrainLess (neregistrovaný)

Extrakce sloupcu, proc nesahnout po cut ?

ls -l | cut -d" " -f6-7

11. 8. 2016 10:11
Palo (neregistrovaný)

Tak ja si neodpustim kritiku. To koli kazdej blbosti instalujete do systemu specialnu utilitku ktora to robi aj ked tam uz mate nieco ovela silnejsie co treba iba spravne pouzit? DIFF naucit sa citat unified diff je snad zakladna zrucnost (diff -u), v tomto formate to dava aj SVNko aj Git a samozrejme sa k tomu naucit pouzivat aj 'patch' Ked to chcem VELMI vizualne VIMDIFF

Ciselne rady Toto akoze na co? Bash uz to ma {1..3} a mam ciselnu radu dokonca aj pekne naformatovanu ak chcem {01..12} a a…