Hlavní navigace

Hrátky z řádky: kombinace procesů podruhé

Ondřej Bojar

Opět se setkáváme u pravidelné pondělní dávky tipů a triků z černé řádky. Základní přesměrování už umíme: standardní a chybový vstup a výstup z nebo do souboru, spojení programů (výstup na vstup) rourou. Podívejme se, jak je to s dalšími typy vstupů a výstupů a možnostmi převádět jeden na druhý.

Mezery na příkazovém řádku

Nejprve se podívejme na příkazovou řádku jako jeden ze vstupů programu. To, co program nakonec dostává, není jeden řetězec obsahující celý příkaz, ale rovnou seznam jednotlivých argumentů. „Nalámání“ příkazové řádky na jednotlivé argumenty provádí ještě bash, zlom přitom typicky nastává na každé posloupnosti mezer. V některých případech je ale zásadní mezeru pokládat za součást argumentu, nikoli jako oddělovač argumentů. Můžeme k tomu užít uvozovky, apostrofy nebo zpětné lomítko. Zde je příklad vyzobnutí prvního sloupce (vlastně slova) z každého řádku, jako oddělovač polí ( -d) totiž udáváme mezeru; oba příklady jsou ekvivalentní:

$ cut -d " " < vstup.txt > vystup.txt
$ cut -d" " < vstup.txt > vystup.txt

V prvním případě program cut dostal na celkem (1+)2 argumenty: nultý byl cut, prostě název programu, první bylo -d a druhý mezera, ve druhém případě cut dostal jen (1+)1 argument: -d. Podle dobrého unixového zvyku cut zareagoval na mezeru bezprostředně následující za -d a po dalším argumentu už se nepídil. (Mimochodem, nultý argument udávající název programu není bez významu, řada programů se opravdu chová různě podle toho, pod jakým jménem byly spuštěny. Nevím, zda i u vás, ale u mne gzip, gunzip a zcat jsou ve skutečnosti stále tentýž program.)

Zde je příklad přejmenování souboru obsahující mezeru ve jméně na slušnější název:

$ mv soubor\ s\ mezerou slusnejsi_nazev

A k čemu ta třetí možnost, apostrof? Zpětné lomítko se nehodí psát opakovaně, uvozovky „chrání“ jen mezeru, otazník a hvězdičku. Jiné speciální znaky, jako například dolar uvozující proměnné, jsou nadále interpretovány. Apostrof naproti tomu vypne všechny speciální znaky:

$ mv 'soubor velmi nestastneho jmena $ ` .txt' slusnejsi_nazev.txt

Apostrof je navíc možné použít k chránění uvozovek a uvozovky ke chránění apostrofů. Následující dva zápisy jsou ekvivalentní, příkaz echo dostane jeden argument sestávající z jedněch uvozovek a jednoho apostrofu:

$ echo \"\'
$ echo '"'"'"

Ještě jeden tip se může hodit: jak zadat tabulátor. Některé programy, například tr, rozumějí zkratkám jako \t. Například sort umí řadit podle udaného sloupce, ale sloupce defaultně odděluje na každém bílém místě. Takto můžete sortu přikázat, ať řadí (abecedně) podle druhého sloupce (odděleného tabulátorem); obě možnosti jsou ekvivalentní:

$ sort -t "<CTRL-V><Tab>" -k2 < vstup > vystup
$ sort -t $'\x9' -k2 < vstup > vystup

Jak otisknout příkazovou řádku či proměnné do výstupu

Příkaz echo nedělá nic víc, než že vypíše všechny své argumenty na standardní výstup, oddělené vždy jednou mezerou. To z něj mimo jiné dělá ideálního pomocníka na to, abyste zjistili, co přesně bash s vašimi argumenty provedl, než je programu předal. Například takto vypíšeme obsah proměnné prostředí  PATH:

$ echo $PATH

A takto zjistíme, kolik adresářů máme vlastně v proměnné PATH zadáno. Povšimněte si, že neděláme nic jiného, než že proměnnou prostředí převádíme (expanzí v bashi na příkazovou řádku a) programem echo do standardního výstupu. Rourami připojíme další zpracování: náhradu dvojteček znakem konce řádku a počítáním řádků:

$ echo $PATH | tr : '\n' | wc -l

A takhle zjistíme, kolik unikátních adresářů v proměnné PATH máme, většinou se jich tam totiž řada opakuje:

$ echo $PATH | tr : ‚\n‘ | sort -u | wc -l

Výstup otisknout do příkazové řádky

Často se hodí možnost předat výstup jednoho programu jako argument jinému programu, čili vlastně takový opak echa. V bashi k tomu slouží zpětné apostrofy. Takto například pošlete mail se subjectem vygenerovaným příkazem hostname, tedy jménem počítače, který mail vygeneroval:

$ mail -s `hostname` ja@doma.cz < text_mailu.txt

Pozor ale na počet argumentů! Pokud by program volaný ve zpětných apostrofech generoval více slov, bash podle svého zvyku z každého slova udělá jeden argument. Jakmile tedy „vnitřní“ program vypíše nějakou mezeru, „vnější“ program pravděpodobně bude zmaten z nečekaných argumentů. Bezpečnější je tedy:

$ mail -s "`hostname`" ja@doma.cz < text_mailu.txt

Výstup programu do proměnné prostředí

Proměnnou prostředí už umíme poslat nějakému programu na vstup a naopak výstup programu dostat na příkazovou řádku. Procvičme si trochu dešifrování rour na příkladu, kde proměnnou prostředí PATH nově nastavíme:

$ export PATH=`echo $PATH | tr : '\n' | sort -u | tr '\n' :`

Příkaz export název_proměnné=nová_hodnota slouží k nastavení proměnné prostředí. Proč slůvko export, o tom si povíme někdy příště. Co tedy uvedená sekvence udělá? Proměnnou PATH nastaví na novou hodnotu, kterou dodá čtyřčlenná roura: stará hodnota PATH se vypíše, dvojtečky nahradí konci řádků, řádky utřídí podle abecedy (a zahodí se duplicity), a pak se zas konce řádků převedou na dvojtečky.

Který program že to vlastně spouštím?

Nedovolím si ukončit tenhle díl, aniž bych vám prozradil, k čemu přesně proměnná PATH slouží. Podle ní bash hledá program, který se má spustit, když napíšete jen jeho jméno. Například sort je ve skutečnosti typicky /bin/sort; pokud by proměnná PATH adresář /bin nezmiňovala, museli byste pokaždé psát celou cestu k programu, čili /bin/sort, jinak by vás bash odmítl hláškou: „bash: sort: command not found“.

Pořadí adresářů (oddělených dvojtečkou, jak už jste si jistě všimli) v proměnné PATH je zásadní, spouští se program nalezený nejdříve. Náš příklad s úklidem proměnné PATH je tedy celkem riskantní: pokud existuje programů sort více, možná se teď po přeházení adresářů začne spouštět jiný, s jinými parametry a zvyklostmi! Takto zjistíte, který sort že se to vlastně spouští:

$ which sort

A nebyl by to unix, kdyby i tohle nebylo s rizikem: which echo vám sice nejspíš vypíše /bin/echo, ale prosté echo bude interní příkaz interpretovaný rovnou bashem. Jako malé cvičení zkuste za pomoci manuálových stránek nachytat bash na švestkách: najít příklad, který odhalí, že echo nespouští /bin/echo. Jako větší cvičení můžete hledat ještě jednu potíž s naším úklidem proměnné PATH, napovím: newline navíc.

Našli jste v článku chybu?