Programozási alapismeretek 1. gyakorlat, 3. csoport, 2006/2007 ősz

Adj már egy oboloszt (=fillért) neki,
mert hasznot akar húzni abból, amit tanul.

Euklidész

Célkitűzés

A tárgy gyakorlatának célja, hogy a hallgatók (haladó felhasználói szinten) megismerjenek egy olyan operációs rendszert, amivel eddig nem biztos, hogy találkoztak, a GNU/Linux rendszert. Elkészítenek továbbá egy weblapot és a félév végén az előadáshoz kapcsolódóan elméleti fogalmakkal kapcsolatos feladatok megoldására is sor kerül.

Időpont

Előadás Szerda 14.00-16.00 Déli Tömb 0-804, Lóczy Lajos előadó
Gyakorlat Hétfő 13.30-15.00 Déli Tömb 0-221
Mentorálás Hétfő 15.15-16.00 Déli Tömb 0-221
Az előadáson és a mentoráláson erősen ajánlott részt venni, a gyakorlatokon megjelenni kötelező!

Elérhetőségek

Előadó Fóthi Ákos
Gyakorlatvezető Riskó Gergely progalap@risko.hu +36-20-340-8772
Mentor Emil Vatai vatai@inf.elte.hu

Követelmények

Eredményes jegy szerzéséhez teljesíteni kell a követelmények mindegyikét, azonban az eredményességen belül az érdemjegy természetesen a teljesítések minőségének összeségét figyelembe véve alakul ki. Az összegyűjthető 185 pontot az alábbiak szerint váltom gyakorlati jegyre:
-60elégtelen
61-90elégséges
91-120közepes
121-150
151-170jeles
170-kitűnő

Bármilyen csalás felfedezése esetén az érintettek csalás által érintett teljesítése (pl. zárthelyi esetén a dolgozat, házi feladat esetén az adott házi feladat) meg nem írtnak számít és a hallgató a jeles vagy kitűnő jegy megszerzésének lehetőségétől elesik. Különösen kirívó (pl. más valaki jön zh-t írni) vagy ismétlődő esetben a csalás tényét az egyetem illetékes személyeinek is jelzem.

A gyakorlatot, mivel azon folyamatos számonkérés van, gyakorlati utóvizsgával teljesíteni nem lehet.

Házi feladatok

Általános (formai) követelmények

1. feladat (6 pont)

Töltsd le Riskó Gergely magyar weblapjáról a robotika alól a graph.c nevű C forrásállományt és annak HTML verzióját! A C fájlt tedd közzé a saját pandorás publikus tárterületeden! Készíts egy új fájlt is eha.txt néven, amibe írd bele az ETR azonosítódat. Az említett három fájlt csatolva, egy emailben küldd el első feladatként, teljesítve a formai követelményeket! Vedd észre, hogy ehhez igazából mindhárom fájlt fel is kell töltened a pandorára, hiszen csak a pandoráról küldött beadandókkal foglalkozom érdemben.

2. feladatsor (összesen 6 pont, feladatonként 2 pont)

3. feladatsor (Összesen 8 pont)

4. feladatsor (Összesen 9 pont)

A vonat.txt nevű fájl pár olyan járat kezdő- és célállomását, valamint indulási és érkezési idejét tartalmazza, amivel Vanessa gyakran utazik. Írjunk parancsfájlokat - amelyeket futtathatóvá téve teszteljünk is a beadás előtt - az alábbi adatok kikeresésére (végig tegyük fel, hogy a városnevek közt nincs egymásbaágyazható, azaz ha szerepel Esztergom nevű település, akkor nincs Esztergom-Kertváros nevű): (A fájlok neve beadáskor a kettőspont előtti rész legyen, mindhárom fájlt csatold a levélhez!)
A parancsfájlok egyedül a kért adatot írják a képernyőre és a vonat.txt nevű fájlt az aktuális könyvtárban keressék (biztosan tudjuk, hogy az ott van, magatoknak is készítsetek belőle egy másolatot a pandorára, miközben tesztelitek a feladatot)!

5. feladatsor (Összesen 12 pont, feladatonként 4 pont)

  1. Írjuk át a múltkori budapestrol.sh feladatot úgy, hogy az tartalmazzon hibakezelést az alábbi módon!
    • Ha paraméter nélkül futtatják, akkor továbbra is az aktuális könyvtárban lévő vonat.txt-t használja, azonban ha ez nem egy közönséges fájl, akkor mielőtt használatba venné, kiír egy hibaüzenetet és 1-es hibakóddal (visszatérési értékkel) kilép.
    • Ha paraméterrel futtatják, de több paraméter van, mint 1, akkor kiírja, hogy legfeljebb 1 paramétert szabad megadni és 2-es hibakóddal lép ki.
    • Ha egy paraméterrel futtatják, akkor a vonat.txt helyett az abban a paraméterben megnevezett fájlt használja, de szintén végez hibakezelést rá és ha nem létezik vagy nem hagyományos fájl, akkor 1-es kóddal lép ki.
    A progam neve legyen ellenorzott.sh és csatold a levélhez!
    Megoldás:
    #!/bin/sh
    FILE=vonat.txt
    if [ "$2" != "" ]
    then
            echo Egy parametert kell megadni
            exit 2
    fi
    if [ "$1" != "" ]
    then
            FILE=$1
    fi
    if [ -f $FILE ]
    then
            cat $FILE | fgrep Budapest: | fgrep -v :Budapest | cut -d: -f2 | sort | uniq
    else
            echo Hibas file: $FILE
            exit 1
    fi
    
  2. Írj parancs fájlt, ami megmondja, hogy az utóbbi időben mikor jelentkeztek be a legkevesebben! Kimenete pl. így nézzen ki:
    errge@pandora:~$ ./legkevesebben.sh
    Nap: Oct 1
    Bejelentkezések: 429
    
    A mai napot ne vedd figyelembe, ugyanis kora reggel futtatva úgy mindig a mai nap jönne ki legkevesebb belépésre!
    A legkevesebben.sh-t csatold a levélhez!
    Megoldás:
    #!/bin/sh
    last | head -n -2 | cut -c 44-49 | uniq -c | tail -n +2 | sort -n | head -n 1 | sed 's/^ *\([0-9]\+\) \(.*\)$/Nap: \2\nBejelentkezések: \1/'
    
  3. Írj olyan parancsfájlt, ami egy paramétert várjon, egy olyan fájlnevet, ami az aktuális könyvtárban nem létezik sem fájl, sem könyvtárként (ezt ellenőrízd!). Ha helyesen egy paramétert adtak meg és az megfelel az említett kritériumoknak, akkor hozza létre ezt a fájlt (tartalma legyen az EHA kódod) és állítsa a fájljogosultságokat úgy, hogy még te is csak olvasni tudd, senki más a rendszeren semmit ne tudjon kezdeni vele (ne írhassa és ne olvashassa)! A parancsfájl neve legyen letrehoz.sh és csatold a levélhez!
    Megoldás:
    #!/bin/sh
    if [ "$1" = "" ] || [ "$2" != "" ] || [ -e "$1" ]
    then
            echo "Hibas parameterek"
            exit 1
    else
            echo RIGHAAT.ELTE >$1
            chmod 0400 $1
    fi
    

6. feladatsor (Összesen 9 pont)

  1. Az otthoni feladatokkal elért eredményeiteket az alábbi módon tartom nyílván egy fájlban:
    $ cat nevsor.txt
    GIJOAAI:gipsz:Gipsz Jakab     :5:7:7:2
    KOVOABI:jsmith:Kovács Vanessa :3:3:6:7
    TOTLAAI:tototto:Tót Ottó      :4:2:7:4
    
    Azaz az első oszlopban van az ETR azonosító, a másodikban a pandorás felhasználói név, amit a teljes név követ és utána jönnek feladatsoronként az elért pontok. Az olvashatóság kedvéért a nevek mögé úgy írok szöközöket, hogy táblázatos forma adódjon. Az ETR kód első három betűje a névből adódik, a negyedik az évfolyamot jelzi valamiképpen (még nem sikerült megfejtenem teljesen :) ), az 5. és 6. betű akkor játszik szerepet ha ugyanazon évfolyamon az első három betű ütközne, a 7. betű a szakra vonatkozóan tartalmaz információt. A most először elsősök kódjában az évfolyam oszlopban O szerepel. A mentorok csak az elsős hallgatók adataira tartanak igényt. Írjunk parancsfájlt, ami a standard bemenetén kapott névsorból kiválogatja az elsősök sorait és azt változatlanul a képernyőre írja, hogy a mentornak elküldhető legyen. A parancs neve legyen mentornak.sh és csatold a levélhez! (3 pont)
    Megoldás:
    #!/bin/sh
    grep '^...O'
    
  2. Készítsünk az előző listához kapcsolódóan egy anonimizálást, ami csak az ETR kódot és pontszámokat hagyja meg, a többit faliújságra kiragasztáshoz X-ekkel helyettesíti:
    $ ./anonim.sh nevsor.txt
    GIJOAAI:XXXXXXXXXXXXXXXXXXXXXX:5:7:7:2
    KOVOABI:XXXXXXXXXXXXXXXXXXXXXX:3:3:6:7
    TOTLAAI:XXXXXXXXXXXXXXXXXXXXXX:4:2:7:4
    
    Ez a parancsfájl (amit anonim.sh néven csatolj a levélhez) most ne a bemenetén várja az inputot, hanem az paraméterben kapott fájlnevet használja, ha az létezik. Ha nem létezik, akkor írjon ki hibaüzenetet! (4 pont)
    Megoldás:
    #!/bin/sh
    if [ "$1" = "" ] || [ "$2" != "" ] || ! [ -f "$1" ]
    then
            echo "Hibas parameterek"
            exit 1
    else
            cat $1 | sed 's/^\([A-Z]\{7\}:\)[^:]\+:[^:]\+/\1XXXXXXXXXXXXXXXXXXX/'
    fi
    
  3. A korábbi vonat.txt fájlban a tíz óránál korábbi időpontok esetében az óra esetén néha kiírtam a kezdő 0-t, néha nem. Javítsuk ezt az inkonzisztenciát, írjunk parancsfájlt, ami úgy módosítja az aktuális könyvtár vonat.txt-jét (nem kell ellenőrízni), hogy mindig ki van írva az órák esetén a vezető 0. A parancsájl neve legyen javit.sh és csatold a levélhez! (2 pont)
    Megoldás:
    #!/bin/sh
    cat vonat.txt | sed 's/:\([1-9]\)\./:0\1./g' >/tmp/vonat.txt.$$
    mv /tmp/vont.txt.$$ vonat.txt
    

7. feladatsor (Összesen 10 pont)

  1. Írj UNIX parancsfájlt nyujtas.sh néven, ami a paraméterként adott számszorosára nyújt minden sort, azaz minden sor annyiszor kerül egymás után a kimenetre, amennyi a paraméter értéke volt. Az egész folyamat előtt ellenőrízzük le, hogy a paraméter egy 1 és 9 közé eső szám (nagyobb nyújtást nem engedünk meg). A parancsfájl szűrő legyen, azaz bementét a standard inputon várja, kimenetét a standard outputra termelje. (5 pont)
    Megoldás:
    #!/bin/sh
    if [ "$1" = "" ] || [ "$2" != "" ] || ! ( echo $1 | grep '^[1-9]$' >/dev/null )
    then
            echo "Hibas parameterek"
            exit 1
    else
            while read SOR
            do
                    for i in $(seq 1 $1)
                    do
                            echo -n "$SOR"
                    done
                    echo
            done
    fi
    
  2. Írj UNIX parancsfájlt tobbe.sh néven, ami kiírja hogy IGAZ, ha első paramétereként adott fájl első sorában több számjegy van, mint kisbetű. Egyébként HAMIS-at ír ki. (5 pont)
    Segítség: gondoljuk át a
    echo -n "itt egy sor" | sed 's/./\0\n/g'
      
    utasítást és vegyük észre, hogy ez pont az órai fuggoleges.sh feladatot oldja meg, csak kicsit rövidebb. Amennyiben az első sort további feldolgozáshoz függőlegesen szeretnéd kiírni, akkor ezt a trükköt is használhatod a korábbi fuggoleges.sh helyett.
    Megoldás:
    #!/bin/sh
    if [ "$1" = "" ] || [ "$2" != "" ] || ! [ -f "$1" ]
    then
            echo "Hibas parameterek"
            exit 1
    else
            SZAMJEGY=$(cat $1 | head -n1 | sed 's/./\0\n/g' | grep '[0-9]' | wc -l)
            KISBETU=$(cat $1 | head -n1 | sed 's/./\0\n/g' | grep '[a-z]' | wc -l)
            if [ $KISBETU -lt $SZAMJEGY ]
            then
                   echo IGAZ
            else
                   echo HAMIS
            fi
    fi
    

Csoport ZH megoldások: PDF PostScript LaTeX

Az évfolyam géptermi ZH megoldásai

1. feladat

Írj UNIX parancsfájlt verzioszam.sh néven, aminek első paramétere egy tetszőleges sztring. A parancsfájl hozza létre az aktuális könyvtárban az első paraméterként kapott nevű fájlt (a névhez biggyesztve egy pontot és egy számot), a lehető legkisebb "verziószámmal". A verziószámok kiosztása 1-től indul. Pl. a ./verzioszam.sh alma parancs hozza létre az alma.1 fájlt, ha olyan még nem volt. Amennyiben pedig ha az alma.1, alma.2 és alma.4 is létezne, de alma.3 még nem, az új fájl neve legyen alma.3!

Megoldás

#!/bin/sh
NEV=$1
I=1
while [ -e "$NEV.$I" ]
do
        I=$((I+1))
done
touch "$NEV.$I"

2. feladat

Írj UNIX parancsfájlt emailcim.sh néven, ami az első paramétereként kapott közönséges fájl sorai közül a standard output-ra írja azokat, melyek pontosan egy formailag helyes emailcímet tartalmaznak, semmi mást.
Formailag helyes egy emailcím, ha tartalmazza a @ (kukac) jelet. Továbbá a kukac előtt csak kisbetűk, számjegyek és pontok lehetnek a kukac utáni részben ugyanezek, de még kötőjelek is. Emailcím csak kisbetűvel, vagy számmal kezdődhet, ponttal (.) nem. A kukac utáni részben kell legyen legalább 1 pont, de az utolsó pont (.) után már csak kisbetűk lehetnek, legalább egy legyen is.

Megoldás

#!/bin/sh
grep '^[a-z0-9][a-z0-9.]*@\([a-z0-9.-]\+\.\)\+[a-z]\{1,\}$' "$1"

3. feladat

Írj UNIX parancsfájlt jonevek.sh néven, ami az 1. paraméterként adott directoryban közvetlenül lévő fájlok közül kiírja azok nevét, melyek alakja unixPQR, ahol P, Q és R számjegyek, és még az is teljesül, hogy PQR, mint 3-jegyű szám hárommal osztható (megj.: 000 is 3-mal osztható szám).

Megoldás

#!/bin/sh
cd "$1"
shopt -s nullglob
for i in unix[0-9][0-9][0-9]
do
        if [ $(($(echo $i | cut -c 5-) % 3)) -eq 0 ]
        then
                echo $i
        fi
done

4. feladat

Írj UNIX parancsfájlt keretez.sh néven, ami paramétereit egyesével bekeretezi pont akkora kerettel, amibe a paraméter belefér. A keretnek a példában adott módon kell kinéznie. A bkeretezett sztringek közvetlenül egymás alatt legyenek:

./keretez.sh szilva "korte      dio"
+------+
|szilva|
+------+
+--------------+
|korte      dio|
+--------------+

Megoldás

#!/bin/sh
while [ $# -ne 0 ]
do
        echo -n + ; echo "$1" | sed 's/./-/g' | sed 's/$/+/'
        echo "|$1|"
        echo -n + ; echo "$1" | sed 's/./-/g' | sed 's/$/+/'
        shift
done

5. feladat

Minden UNIX gépen van egy /etc/group fájl. Ennek tartalma ehhez hasonló:

ajtonallo::100:errge,lenart,vezerb
felugyelo:x:120:bzsr,errge,heha,lenart,spala,vezerb
fenymasolo::130:heha
forgalmazo:x:90:bzsr
gonoszkodo:x:105:
nevsorozo::140:errge:spala

Minden sorban egymástól kettősponttal elválasztva sorrendben a csoportnév, jelszó (ez többnyire hiányzik, vagy x betű van helyette), csoportazonosító és a csoport tagjainak azonosítói vannak. Utóbbiakat , (tehát vessző) választja el egymástól. Az is lehet, hogy az utolsó mező, tehát a csoportot alkotó felhasználók listája hiányzik, ekkor a csoportnak nincs egy tagja sem, a sor : jelre végződik (a példában az utolsó előtti sor ilyen).
Írj UNIX parancsfájlt csoport.sh néven, ami kiírja azoknak a csoportoknak a nevét (csak a nevét!) a /etc/group fájlból, amelyeknek legalább 2 tagja van. (A példában a felugyelo csoportnak például hat tagja van.)

Megoldás

#!/bin/sh
grep -v ':[a-z]*$' /etc/group | cut -d: -f1

Segédanyagok

Fóthi Ákos: Bevezetés a programozáshoz (ELTE Eötvös Kiadó)
Brian W. Kernighan, Rob Pike: The Unix programming environment. Prentice Hall, ISBN 3-446-14273-8
Linux Shell Scripting Tutorial
man oldalak