Shellové skriptovanie: `echo` a presmerovanie

Ahoj svet

Notorický „úplne prvý program“ je jednoduchý:

echo "Hello World"

Výstupom je

Hello World

Príkaz echo v tomto prípade dostal jeden parameter, t. j. jeden reťazec (string) obsahujúci medzeru, ktorý vypísal na štandardný výstup. Za reťazec potichu dodal znak pre nový riadok (\n).

Existujú aj minimálne dva iné spôsoby výpisu takétoho textu, ale tie teraz nechajme tak.

Presmerovanie vstupu a výstupu

Mnoho unixovských programov dokáže fungovať ako mlynček na mäso: z jednej sa doň tlačia dáta, vo vnútri melú a na výstupe vychádzajú v pozmenenej podobe.

Dáta v tomto prípade predstavuje takmer vždy text: teda postupnosť znakov. (Ostatné prípady sú binárne dáta, teda bajty v „nečitateľnej” podobe).

Kuchynský mlynček má obvykle jeden výstup (mleté mäso padá do misy). Ale už taký odšťavovač využíva viacero výstupov: jedným otvorom tečie šťava a do separátnej nádobky putujú nepomleté šupiny.

Unixovské programy môžu svoj výstup tak isto zapisovať do viacerých kanálov. Ak nepoužijeme žiadne finty, výstup programu (“šťava”) putuje na štandardný výstup. Ak program zapisuje do viacerých kanálov, všetky sa zobrazia na obrazovke.

Príkaz echo je ukážkou programu, ktorý berie vstup z parametrov príkazového riadka a zapisuje do štandardného výstupu:

echo "Ahoj svet"

Štandardný výstup akéhokoľvek programu môžeme presmerovať do súboru — stačí na to použiť zobák: >.

echo "Ahoj svet" > pozdrav.txt

Všetok text zapísaný príkazom echo skončí v súbore pozdrav.txt. Skontrolovať to môžeme cez

cat pozdrav.txt

Vezmime si iný príklad. Pokúsme sa vypísať obsah neexistujúceho adresára s názvom NIC:

ls NIC

Výsledkom je výpis:

ls: cannot access NIC: No such file or directory

Príkaz ls nedokáže zobraziť obsah a preto nás rozosmutní chybovou hláškou. Tá však neputovala do štandardného výstupu, ale do chybového výstupu (stderr). Na obrazovke sa to zobrazilo tak či tak (skrytá chybová hláška je totiž na nič — chceme predsa vedieť, že niečo sa pri behu pokazilo).

V mnohých prípadoch sa však chceme zámerne zbaviť chybových hlášok. Dosiahneme to jednoducho — presmerovaním chybového výstupu do čiernej diery.

V Linuxoch je ňou špeciálny súbor /dev/null, do ktorého môžeme zapisovať koľko len chceme a čo chceme, akýkoľvek obsah sa totiž automaticky stratí. Ak presmerujeme chybový výstup do tohto súboru, rovno sa ho zbavíme.

V skutočnosti môžeme uviesť pri presmerovaní deskriptor súboru (file descriptor), čo je číslo identifikujúce konkrétny súbor, do ktorého môžeme presmerovať výstup (ale aj z ktorého môžeme presmerovať vstup, o čom neskôr.)

Štandardnému výstupu prislúcha deskriptor 1, a chybový výstup je spriahnutý s číslom 2. Môžeme teda spraviť:

ls NIC 2> /dev/null

Tým sme presmerovali chyby do čiernej diery a prípadné normálne výpisy uvidíme civilizovaným spôsobom.

Poznamenajme len, že nasledovné dva príkazy robia to isté: presmerujú štandardný výstup do čiernej diery. Deskriptor 1 prislúchajúci štandardnému výstupu môžeme totiž vynechať.

ls /etc 1> /dev/null
ls /etc > /dev/null

Presmerovanie vstupu

Príkaz echo aj ls brali vstupy z parametrov príkazového riadka. Linuxovské mlynčeky sú však často uspôsobené na filtrovanie: načítavajú dáta z štandardného vstupu a zapisujú ich do vhodného kanála.

Skúste si pustiť príkaz tr, ktorý nahradí každú samohlásku áčkom:

tr "aeiou" "a"

Program čaká na dáta zo štandardného vstupu, ktorým je implicitne klávesnica. Skúste písať a enterovať:

sedzi mucha na scene

Po odenterovaní uvidíte

sadza macha na scana

Takto si môžete dopisovať s tr-kom do vôle a keď vás to prestane baviť, klávesovou skratkou Ctrl + D zašlete znak konca súboru, čím ukončíte zadávanie textu na štandardný vstup a tým aj beh samotného tr.

Mnohokrát sa žiada presmerovať do mlynčekovského štandardného vstupu obsah nejakého súboru. Na to slúži operátor <, ktorý má „arabský štýl zápisu“ (sprava doľava).

Vytvorme najprv súbor:

echo "sedzi mucha na scene" > popevok.txt

Následne presmerujme obsah súboru popevok.txt na štandardný vstup príkazu tr:

tr "aeiou" "a" < popevok.txt

Rúry

Vieme už presmerovať štandardný / chybový výstup do súboru a zvládli sme aj opak: vysypanie, teda presmerovanie obsahu súboru na štandardný vstup programu.

Najčastejšou fíčurou je však vzájomné spájanie dvoch programov: výstup jedného programu presmerujeme na vstup druhého programu. (V kuchynskej analógii už máme problém — presmerovať mleté mäso do odšťavovača nie je ktovie čo ;-)))

Takéto prepojenie sa dosahuje pomocou operátora | (rúra, pajpa, pipe). Názov nie je úplne náhodný, predstavte si totiž údaje, ktoré vypľuje jeden nástroj, tečúce rúrou do ďalšieho nástroja.

Vieme, že ls vypisuje obsah adresára. Príkaz tail zase zoberie zo štandardného vstupu len posledných n riadkov (implicitne 10) a zvyšné bude ignorovať. Tieto dva nástroje môžeme skombinovať a vypísať tak 10 najväčších súborov v aktuálnom adresári:

ls -lSr | tail

Parameter -l znamená long listing, teda dlhý výpis položiek (každá na samostatnom riadku, s podrobnými informáciami), -S usporiada položky podľa veľkosti zostupne a -r otáča poradie usporiadavania.

Rúru možno použiť aj viackrát, čím možno radiť nástroje do kolón (tak ako máte kolóny kamiónov). Nasledovný príkaz vezme výsledok ls, pomocou grep odfiltruje položky, ktoré sa nezačínajú na “d” (teda zahodí položky, ktoré sú adresármi) a z výsledku zoberie posledných 10 riadkov.

ls -lSr | grep -v ^d | tail

Rúry a presmerovania

Samozrejme, rúry a presmerovania môžeme radostne kombinovať! Nasledovný príkaz odfiltruje z /etc/passwd len tých používateľov, ktorí majú domovský adresár v /home, následne ich spočíta a výsledné číslo zapíše do súboru home_users.txt

grep "/home` /etc/passwd | wc -l > home_users.txt

Zbytočný cat

Mnoho začiatočníkov v Linuxe ignoruje existenciu operátora < — možno ich straší opačný smer čítania — a namiesto toho používajú kombináciu cat a rúry.

Úloha “vypíšte informácie o používateľovi novotnyr” sa samozrejme dá dosiahnuť aj takto:

cat /etc/passwd | grep novotnyr

Príkaz cat naozaj zoberie súbor a zapíše jeho obsah na štandardný výstup. Je to však úplne zbytočné, pretože úplne rovnaký účinok dosiahneme cez

grep novotnyr < /etc/passwd

Táto konštrukcia je oveľa efektívnejšia: namiesto dvoch príkazov sa volá len jeden a dokonca (ale to je technická záležitosť) sa ušetrí jedno spustenie separátneho procesu s tzv. podshellom.

A dokonca sa to dá ešte korektnejšie. Dokumentácia k grep hovorí, že posledný parameter môže byť cesta k súboru. V takom prípade prebehne filtrácia priamo nad súborom. Môžeme sa tak úplne zbaviť presmerovania!

grep novotnyr /etc/passwd

Nadbytočné používanie catu si dokonca vyslúžilo v jednej diskusnej skupine špeciálne ocenenie udeľované s týždennou periodicitou. Naozaj, mnohokrát nie je potrebné!

2 thoughts on “Shellové skriptovanie: `echo` a presmerovanie

Pridaj komentár

Vaša e-mailová adresa nebude zverejnená. Vyžadované polia sú označené *