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.