Příklady na procvičení shellu ============================= (řešení je v reseni_shell.txt) ------------------------------------------------------------------------------- A) základní příkazy pro manipulaci se soubory ------------------------------------------------------------------------------- 1. Kolik v systému existuje uživatelských účtů? 2. Vypište řádky č. 10 až 20 souboru /etc/passwd. 3. Kolik souborů (všech, včetně jmen začínajících tečkou) je aktuálním adresáři? 4. Uložte manuálovou stránku k shellu bash do souboru bash.man a pak spočítejte, kolik je v souboru slov. 5. Vytvořte soubor xxx, který má čas poslední modifikace stejný jako soubor /etc/services. 6. Napište příkaz, který bude vstup z klávesnice ukládat do souborů s1 a s2. 7. Uložte do souboru xxx první a poslední řádek souboru /etc/group. 8. Napište příkaz, který bude vypisovat obsah adresáře /bin po stránkách na obrazovku (pomocí more nebo less) a zároveň ukládat do souboru ls-bin. 9. Vytvořte adresář dir a v něm soubor takový, že nepůjde zjistit jméno tohoto souboru pomocí ls, ale kdokoliv, kdo zná jméno souboru, do něho může zapisovat, ale ne číst. Výjimkou je vlastník souboru, který ho může číst, ale ne zapisovat. Ověřte funkčnost ve spolupráci s jiným uživatelem. Jakými různými způsoby lze nastavit požadovaná práva? ------------------------------------------------------------------------------- B) komunikace mezi uživateli, identifikace uživatelů ------------------------------------------------------------------------------- 1. Pošlete svému kolegovi na obrazovku výpis obsahu (s podrobnými informacemi o souborech) adresáře o jednu úroveň výše, než je aktuální adresář. 2. Pošlete svému kolegovi na obrazovku obsah souboru /etc/profile. 3. Pošlete svému kolegovi e-mailem (subject bude "Soubor") obsah souboru /etc/inetd.conf. 4. Jak způsobíte, aby se vám veškerá došlá pošta ukládala nejen do standardního mailboxu, ale i do souboru ~/inbox? Připravte soubor ~/.inbox tak, aby byl přístupný pouze vám. 5. Zjistěte, do kolika skupin uživatelů patříte. 6. Nastavte forward pošty tak, aby se do souboru ~/prehled_posty pro kazdy dosly mail zapisovalo datum jeho prichodu. ------------------------------------------------------------------------------- C) diff, comm, cut, paste, split, sort, tr ------------------------------------------------------------------------------- 1. Vypište čísla skupin, která jsou použita v /etc/passwd. Každé číslo by mělo být vypsáno právě jednou. 2. Vypište obsah /etc/passwd setříděný (numericky) podle UID. 3. Vypište obsah /etc/group setříděný podle jména skupiny. 4. Vypište plná jména uživatelů setříděná sestupně podle login name. 5. Vypište loginy uživatelů ve dvou sloupcích, v levém v původním tvaru, v pravém se všemi malými písmeny převedenými na velká. Sloupce jsou odděleny znakem '='. 6. Vypište loginy uživatelů oddělené mezerami po pěti na řádku, setříděné zleva doprava. 7. Vypište jména skupin do 10-ti řádků, na každém řádku jsou skupiny oddělené čárkami. 8. Změňte v souboru /etc/passwd každý výskyt znaků 'w' a 'W' na '@' a pomocí diff zjistěte, které řádky byly změněny. 9. Vypište čísla skupin, která existují v /etc/group, ale nejsou použita v /etc/passwd. ------------------------------------------------------------------------------- D) find ------------------------------------------------------------------------------- 1. Napište, příkaz, který vypíše počet všech pro vás viditelných adresářů počínaje rootem ('/'). 2. Napište, příkaz, který smaže všechny soubory 'core' staré aspoň 5 dní. 3. Napište, příkaz, který vypíše seznam všech rootem vlastněných programů, které jsou spustitelné pro uživatele, skupinu i ostatní uživatele. 4. Napište, příkaz, který smaže všechny objektové soubory (*.o) nezměněné aspoň 2 dny v podstromu vašeho domovského adresáře. 5. Napište, příkaz, který vypíše počet všech záložních kopií souborů editovaných editorem vim (*~) vlastněných uživateli 'root' a 'nobody'. 6. Napište, příkaz, který u všech obyčejných souborů v podstromu vašeho domovského adresáře, které mají nastavené právo spuštění, vypíše informace o jejich typu (zda jde o binární spustitelné programy, shellové skripty, apod.) 7. Napište, příkaz, který pro každý soubor 'core' v podstromu vašeho domovského adresáře vypíše jeho velikost v bytech. 8. Napište, příkaz, který vypíše počet všech speciálních souborů zařízení (znakových i blokových) v celém stromu souborů. 9. Napište, příkaz, který vypíše jména všech zdrojových souborů v C (končí příponou .h nebo .c) vlastněných vámi nebo uživatelem root v celém stromu adresářů. ------------------------------------------------------------------------------- E) vi ------------------------------------------------------------------------------- 1. Vyzkoušejte si základní editační akce (spuštění editoru, pohyb kurzoru, vkládání, mazání, přepisování znaků, uložení souboru, ukončení editoru). 2. Vyzkoušejte si práci s bloky (přesun, kopírování a mazání bloků textu) a značkami (označení místa v textu). 3. Vyzkoušejte si práci s více soubory, v editoru vim i s více okny. 4. Vyzkoušejte si vyhledávání a nahrazování v textu. 5. Vyzkoušejte si další možnosti editoru (konfigurační proměnné, makra, další editační příkazy). Je dobré si pustit gvim nebo vim a pak si projít help. 6. Zrušte v /etc/services všechny řádky, a obsahují řetězec 'udp'. 7. V /etc/services zakomentujte (vložením '#' na začátek) řádky obsahující řetězec '/tcp'. 8. V /etc/services ponechte pouze komentáře (řádky začínající '#'). 9. Změňte řádek v HTML souboru Obrazek: ... na Obrazek: obrazek... Řešení by mělo fungovat pro libovolnou pozici kurzoru na řádku a bez použití šipek (a jejich ekvivalentů h, l, space, backspace). 10. Změňte řádek toto je orbaceen na Toto je obracene Řešení by mělo fungovat pro libovolnou pozici kurzoru na řádku a bez použití šipek (a jejich ekvivalentů h, l, space, backspace). 11. Změňte radek 2 radek 1 na radek 1 radek 2 Předpokládejte, že kurzor je na 'radek 1'. 12. Změňte řádek ve zdrojovém textu programu v jazyce C if((outf=open(argv[2],O_EXCL|O_TRUNC,0666))==-1) { na if((outf=open(argv[2],O_WRONLY|O_CREAT,0604))==-1) { 13. Změňte řádek ve zdrojovém textu programu v jazyce C if((outf=open(argv[2],O_WRONLY|O_CREAT|O_TRUNC,0666))==-1) { na if((outf=open(argv[2], O_WRONLY|O_CREAT|O_TRUNC, 0666))==-1) { Řešení by mělo fungovat pro libovolnou pozici kurzoru na řádku a bez použití šipek (a jejich ekvivalentů h, l, space, backspace) a příkazu :s. 14. Napište příkaz, který otočí pořadí řádků v souboru (první bude poslední, druhý předposlední, atd.). 15. Napište postup pro otočení pořadí znaků na řádku s kurzorem (z 'abcd' udělá 'dcba') bez použití externího příkazu (tj. ne ':.!rev'). ------------------------------------------------------------------------------- F) regulární výrazy, grep ------------------------------------------------------------------------------- 1. Vypište řádky souboru /etc/passwd, které odpovídají informacím o uživatelích - studentech se starým loginem (4 písmena následovaná 4 číslicemi). 2. V souborech s příponami .h, .c a .cc v aktuálním adresáři najděte direktivy preprocesoru jazyka C pro definování maker. Řádky s těmito direktivami začínají řetězcem '#define' 3. Najděte e výpisu získaném příkazem 'ls -l' všechny programy - spustitelné soubory, které mají právo EXECUTE pro uživatele, skupinu i ostatní. Nezapomeňte zahrnout do výpisu i SUID programy. 4. Najděte e výstupu příkazu 'mount' všechny podstromy připojené ze serveru 'ss1000'. Odpovídající řádky začínají jménem serveru ukončeným dvojtečkou, např. ss1000:/var/mail on /SPIS/mail type nfs (vers=2,dev=14000a) 5. Najděte ve výpisu adresáře příkazem 'ls -1p' všechny adresáře (za jménem mají připojený znak '/') a symbolické linky (připojený znak '@'). 6. Najděte e výstupu příkazu 'diff' řádky, které označují řádky obsažené jen v jednom z porovnávaných souborů - na začátku řádku je '< ' (menšítko, mezera), nebo '> ' (většítko, mezera). 7. Najděte v Postscriptovém souboru komentář obsahující počet stránek. Řádek s tímto komentářem má tvar: %%Pages: n kde 'n' je dekadické číslo. 8. Najděte v souboru řádky končící dekadickým číslem. 9. Najděte v souboru řádky začínající hexadecimálním číslem: 0xN, kde N je posloupnost číslic a písmen A-Z, a-z. 10. Najděte řádky souboru /etc/passwd, které odpovídají uživatelům skupiny students (GID=200). 11. Najděte řádky souboru /etc/passwd, které odpovídají studentům (se starými loginy), kteří mají správné UID. UID studenta se získá přidáním číslice 1 před čtyřmístné číslo z login-name. 12. Najděte řádky souboru /etc/passwd, které obsahují informace o uživatelích s domovskými adresáři v adresáři '/home'. 13. Najděte řádky souboru /etc/passwd, které odpovídají uživatelům s full name obsahujícím aspoň dvě mezery, např. 'UNIX Lab Superuser', 'Rfind Daemon and Fsdump,SGI'. Nezapomeňte, že regulární výraz musí specifikovat správné pole záznamu v /etc/passwd. 14. Najděte řádky souboru /etc/group, které odpovídají skupinám s trojmístným číslem skupiny. 15. Najděte řádky souboru /etc/passwd, které odpovídají uživatelům s username o délce 3 až 7 znaků. 16. Najděte řádky souboru /etc/passwd pro uživatele se stejným UID a GID. 17. Najděte v seznamu souborů (získaném např. příkazem find) soubory, které v cestě obsahují adresáře 'lib', nebo 'bin' a končí příponou '.so'. 18. Najděte ve výstupu příkazu 'ls -l' soubory, které mají stejná přístupová práva pro vlastníka, skupinu a ostatní. 19. Najděte v konfiguračním souboru /etc/inetd.conf (konfigurace démona inetd) všechny povolené síťové TCP služby. Popis každé služby je na samostatném řádku, položky na řádku jsou oddělené libovolným počtem bílých znaků (mezery nebo tabulátory, můžete uvažovat pouze mezery), řádky začínající znakem '#' jsou komentáře. TCP služby mají ve 3. položce řetězec 'tcp'. ------------------------------------------------------------------------------- G) ed, ex, sed ------------------------------------------------------------------------------- 1. Vytvořte skript pro editor ed, který vloží na začátek souboru 'skript' řádek '#!/bin/bash' a zakomentuje (vloží '#' na začátek řádku) všechny bloky řádků tvaru /* ... komentář ... */ ... 2. Vytvořte skript 'skript.sed' pro sed tak, že sed -f skript.sed soubor.in > soubor.out vloží na začátek souboru řádek '#!/bin/bash' a zakomentuje (vloží '#' na začátek řádku) všechny bloky řádků tvaru /* ... komentář ... */ ... 3. Vytvořte skript pro editor ex, který v editovaném souboru nahradí všechna malá písmena na začátku slova velkými a slova obsahující písmeno e nebo E napíše celá velkými písmeny. 4. Napište emulátor 'turing.comp' Turingových strojů v editoru sed. Vstupem je soubor 'turing.in', na každém řádku obsahuje jednu instrukci TS ve tvaru qsQSM: q=stav (dekadické číslo), s=čtený symbol (libovolný znak kromě metaznaků sedu, '_' je blank), Q=nový stav, S=nový symbol, M=pohyb -/0/+ (doleva, na místě, doprava). Začíná se s hlavou na začátku pásky ve stavu 0. Definice TS může navíc obsahovat prázdné a kometářové řádky (začínají znakem '#'). Příkazem sed -f turing.comp turing.in > turing.out se vygeneruje nový skript pro sed, pomocí sed -f turing.out se spustí simulace. Každý řádek vstupního souboru se bere jako jeden vstup pro TS, simuluje se výpočet TS, vypisuje se konfigurace po každém kroku a nakonec se vypíše výstup a pokračuje se dalším řádkem. 5. Pomocí sedu změňte C-čkové komentáře /* ... */ na C++-styl komentářů // ... a naopak. 6. Pomocí sedu v souboru /etc/passwd přidejte k full-name studentů se starým loginem (mají login name ve tvaru 4 písmena a 4 číslice) řetězec "student". 7. Napište skript pro editor ed, kterým ze shellového skriptu odstraníte komentáře (řádky obsahující jen komentář budou zrušeny úplně, jinak bude ponechán zbytek řádku před komentářem). 8. Pomocí editoru sed ze shellového skriptu odstraňte komentáře (řádky obsahující jen komentář budou zrušeny úplně, jinak bude ponechán zbytek řádku před komentářem). 9. Pomocí editoru sed změňte domovské adresáře uživatelů v /etc/passwd z tvaru /afs/ms/uX/Xxxx na /home/Xxxx. 10. Pomocí editoru sed změňte domovské adresáře uživatelů v /etc/passwd z /home/Xxxx na /afs/ms/uX/Xxxx (ve treti urovni se jmeno adresare sklada z 'u' a prvniho pismene login name). 11. Pomocí editoru sed smažte z textu vše kromě prvního dekadického čísla na každém řádku. ------------------------------------------------------------------------------- H) expanzní znaky ------------------------------------------------------------------------------- 1. Pomocí expanzních znaků shellu zapište výraz, který vybere všechny soubory v aktuálním adresáři kromě souborů '.' (aktuální adresář) a '..' (rodičovský adresář). 2. Pomocí expanzních znaků shellu zapište výraz, který vybere všechny skryté soubory (soubory, jejichž jméno začíná znakem '.') v aktuálním adresáři, kromě souborů, které mají na druhém místě ve jménu velké písmeno. 3. Pomocí expanzních znaků shellu zapište výraz, který vybere všechny zdrojové soubory v jazyce C (soubory s příponou '.h' nebo '.c'), jejichž jméno začíná velkým písmenem. 4. Pomocí expanzních znaků shellu zapište výraz, který vybere všechny knihovny (soubory se jménem začínajícím 'lib' a s příponou '.a' nebo '.so'. 5. Pomocí expanzních znaků shellu zapište výraz, který vybere všechny soubory se jménem dlouhým aspoň 3 znaky a končícím číslicí. 6. Pomocí expanzních znaků shellu zapište výraz, který vybere všechny soubory se jménem začínajícím písmenem 'S' nebo 'K', která následuje 2 číslice a pak libovolný řetězec (takové soubory se vyskytují v adresářích /etc/rc?.d). 7. Pomocí expanzních znaků shellu zapište výraz, který vybere všechny skryté soubory (jejich jméno začíná '.'), které mají ve jménu číslici. 8. Pomocí expanzních znaků shellu zapište výraz, který vybere všechny soubory v prvních dvou úrovních stromu adresářů (tj. obsah adresáře '/' a adresářů v něm (mimo skrytých souborů - se jménem začínajícím '.'). 9. Pomocí expanzních znaků shellu zapište výraz, který vybere skripty, které se spouštějí při startu nebo změně úrovně běhu systému, tj. soubory v adresářích '/etc/rc<číslice>.d'. 10. Pomocí expanzních znaků shellu zapište výraz, který vybere všechny soubory s aspoň dvojznakovým jménem začínajícím velkým písmenem. 11. Pomocí expanzních znaků shellu zapište výraz, který vybere všechny soubory se jménem končícím trojznakovou příponou, jméno a přípona jsou oddělené tečkou (např. soubor.txt). 12. Pomocí expanzních znaků shellu zapište výraz, který vybere zdrojové soubory pro překladač C a objektové soubory (soubory s příponami '.c', '.h', '.o'). 13. Pomocí expanzních znaků shellu zapište výraz, který vybere skryté soubory (jméno začíná '.'), které mají ve jménu znak podtržítko nebo minus. 14. Pomocí expanzních znaků shellu zapište výraz, který vybere všechny soubory statických knihoven (jméno začíná 'lib' a končí '.a') v adresářích lib nacházejících se v druhé úrovni stromu adresářů (např. /usr/lib nebo /big/lib). ------------------------------------------------------------------------------- I) přesměrování, kombinování příkazů, proměnné v shellu, metaznaky ------------------------------------------------------------------------------- 1. Exit status řádku cmd1 | cmd2 je exit status posledního příkazu v rouře, tj. cmd2. Jak lze donutit shell, aby vracel exit status prvního příkazu roury? 2. Co udělá následující příkaz a proč? find `find / -name '*bin*' -type d` -type f \( -perm -4000 -o -perm -2000 \) \ -exec ls -l {} \; 3. Napište skript pro spouštění příkazů pomocí e-mailu. Program dostane na vstup dopis ve tvaru: From: Subject: pustí příkaz a na vstup mu dá . Výstup příkazu (standardní i chybový) a návratový kód pošle zpět na adresu . 4. Co udělá následující příkaz a proč? a=1;b=2;{ a=LEVY;echo $a >&2;}|{ b=PRAVY;echo $b;tr 'A-Z' 'a-z';};\ echo "A=$a,B=$b" Jak se liší od a=1;b=2;{ a=LEVY;echo $a;}|{ b=PRAVY;echo $b;tr 'A-Z' 'a-z';};echo "A=$a,B=$b" 5. Co udělá následující příkaz a proč? { { { echo 1aaa;echo 2bbb >&2;} 3>&1 1>&2 2>&3|\ { tr 'a-z' 'A-Z';echo 2tr >&2;} 2>&1 } 3>&1 1>&2 2>&3 }>out 2>err 6. Co udělá následující příkaz a proč? find /*/lib \( -type f -o -type l \) | xargs stat 7. Co udělá následující příkaz a proč? a=0;cat /etc/group|while read l;do a=`expr $a + 1`;done;echo $a Jaká byla pravděpodobná zamýšlená funkce tohoto příkazu a jak by se měl příkaz opravit? 8. Co udělá následující příkaz a proč? a=a; b=b; { echo $a; a=$a$b; echo $a; cd /etc; } > x ; echo $a Jak se liší od a=a; b=b; ( echo $a; a=$a$b; echo $a; cd /etc ) > x ; echo $a 9. Co udělá následující příkaz a proč? { cat a;cat b;cat c; }>out Jak se liší od cat a>out;cat b>out;cat c>out ------------------------------------------------------------------------------- J) řídicí struktury, test, expr, eval, signály ------------------------------------------------------------------------------- 1. Co udělá následující příkaz a proč? while read f out;N=`expr $N + 1`;done Čím se liší od příkazu: N=0;while [ $N -lt 10 ];do echo $N;N=`expr $N + 1`;done>out 5. Napište, příkaz (skript), který dostane 2 parametry DIR a USER a vypíše velikost diskového prostoru, který v podstromu DIR zabírá uživatel USER. 6. Napište, příkaz (skript), který pro každého uživatele vypíše jeho login-name, jmého jeho skupiny, full-name a vsechny jeho procesy setříděné sestupně podle čísla procesu. 7. Napište, příkaz (skript), který vypisuje všechny skupiny a pro každou skupinu seznam login-names uživatelů, kteří do ní patří (uživatelé, kteří jsou uvedeni v příslušném řádku /etc/group a uživatelé, kteří mají skupinu nastavenou jako primární v /etc/passwd). Jména uživatelů jsou oddělena mezerami. 8. Napište, příkaz (skript), který pro každého uživatele vypíše jeho login-name a počet a celkovou velikost jím vlastněných souborů v adresářích '/tmp' a '/var/tmp'. 9. Napište, příkaz (skript), který pro každého nalogovaného uživatele vypíše jeho login name, full name a jména terminálů, kde je nalogovaný. Záznam by měl být na jedné řádce ve tvaru: 'login:full:term1,term2,term3,...'. 10. Napište, příkaz (skript), který kontroluje, zda všechny svazky uvedené v /etc/fstab jsou připojené na správných adresářích (zjistíte ze souboru /etc/mtab nebo příkazem mount). Vypisuje jména svazků, které nejsou správně připojené a adresář, kam by měly být připojené (podle /etc/fstab). 11. Napište, příkaz (skript), který vypisuje plná jména uživatelů, kteří jsou právě nalogovaní (pro zjištění nalogovaných uživatelů použijte příkaz who). Každého uživatele vypisuje pouze jednou. 12. Napište, příkaz (skript), který před každý parametr počínaje třetím vloží řetězec, zadaný jako druhý parametr, a takto modifikovaný seznam parametrů předá příkazu, který je zadaný jako první parametr. Tj. např. 'PARAMS cmd -x 1 2 3' zavolá příkaz 'cmd -x 1 -x 2 -x 3'. 13. Napište, příkaz (skript), který čte řádky ze vstupu, rotuje je vlevo o počet slov zadaných jako parametr a výsledné řádky vypisuje. Např. s parametrem '2' řádek 'a b c d e' vypíše jako 'c d e a b'. 14. Napište, příkaz (skript), který zkopíruje všechny soubory v aktuálním adresáři, které mají příponu '.c', do souborů se stejným jménem a příponou '.bak'. 15. Napište, příkaz (skript), který vypisuje obsah adresáře, který dostane jako parametr. Když narazí na jméno podadresáře, zeptá se uživatele, zda má vypsat obsah podadresáře. Podle odpovědi ho buď vypíše, nebo přeskočí. Pracuje rekurzivně, tj. ptá se i na podadresáře podadresářů. 16. Napište, příkaz (skript), který vypíše seznam všech manuálových stránek, které jsou v sekci zadané jako 1. argument a jejich názvy začínají řetězcem zadaným ve 2. argumentu. Adresáře s manuálovými stránkami jsou uvedeny (oddělené dvojtečkou) v proměnné MANPATH, jednotlivé sekce jsou v podadresářích 'man<č. sekce>'. Soubory s manuovými stránkami mohou mít různé přípony. Vypisujte pouze jména (setříděná podle abecedy), ne cesty ani přípony. 17. Napište, příkaz (skript), který dostane jako parametr jméno souboru, ve kterém je na každém řádku jméno souboru. Jednotlivá jména jsou postupně nabízena uživateli, který si může u každého souboru vybrat jednu z akcí: X (konec skriptu), L (zobrazit obsah souboru, po zobrazení se opět zeptá na akci pro stejný soubor), R (smazat soubor), N (další soubor). 18. Napište, příkaz (skript), který výstup příkazu 'ls -l' upraví tak, že vypisuje jen plné jméno vlastníka souboru, číslo jeho skupiny a jméno souboru. 19. Co udělá následující příkaz a proč? i=1;a1=A;a2=B;a3=C;b=`eval echo \\\$a\`expr $i + 1\``;echo $b 20. Napište, příkaz (skript), který vypíše (setříděná podle abecedy) jména všech programů, které můžete spustit bez udání plné cesty (tj. všechny soubory v adresářích napsaných v proměnné $PATH, ke kterym máte právo execute)? ------------------------------------------------------------------------------- K) awk ------------------------------------------------------------------------------- 1. Napište awk skript, který dostane jako parametr jméno HTML dokumentu a vypíše všechny URL, na které z daného dokumentu vedou odkazy. Předpokládejte odkazy ve tvaru , kde 'A HREF' může být libovolná kombinace malých a velkých písmen. 2. Napište awk skript, který v textu zakomentuje všechny odstavce, které začínají komentářovým řádkem. Znak uvozující komentář je zadán jako argument, odstavce se oddělují prázdným řádkem. Př. (\n je znak konce řádku) # radek 1 # radek 1 radek 2 # radek 2 radek 3 --> # radek 3 \n \n odstavec 2 odstavec 2 3. Napište awk skript, který formátuje text po odstavcích (oddělují se prázdným řádkem) do zadaného počtu sloupců. Program vždy vezme odstavec a napíše ho na co nejmenší počet řádků tak, aby k přechodu na nový řádek nedocházelo uprostřed slova. 4. Napište skript pro shell+awk, který simuluje chování příkazu head. Rozpoznejte přepínač -n udávající počet vypisovaných řádek. Shell použijte jen pro zpracování parametrů pro awk. Napište totéž pro gawk (bez shellu, s využitím proměnných ARGC, ARGV v gawk). 5. Implementujte zásobníkový kalkulátor pomocí awk. Kalkulátor čte ze vstupu a zpracovává příkazy: p ... vytiskne vrchol zásobníku e ... smaže vrchol zásobníku a číslo ... vloží číslo na vrchol zásobníku d ... zduplikuje číslo na vrcholu zásobníku + ... vezme ze zásobníku číslo pod vrcholem a na vrcholu, sečte je a výsledek vloží na zásobník - ... vezme ze zásobníku číslo pod vrcholem a na vrcholu, odečte je a výsledek vloží na zásobník * ... vezme ze zásobníku číslo pod vrcholem a na vrcholu, vynásobí je a výsledek vloží na zásobník / ... vezme ze zásobníku číslo pod vrcholem a na vrcholu, vydělí je a výsledek vloží na zásobník w prom ... uloží číslo na vrcholu zásobníku do proměnné prom r prom ... vloží na zásobník obsah proměnné prom s ... zobrazí celý zásobník Chybný příkaz způsobí vypsání '?'. Pozor na kontrolu prázdného zásobníku a dělení nulou. 6. Napište skript pro awk, který simuluje chování příkazu tail v základní formě bez přepínače pro počet řádků, tj. vždy vypíše posledních 10 řádků souboru.