<!doctype linuxdoc system>

<!-- 
     An introduction to bash shell programming
 -->

<!-- Title information -->

<article>
    <title>Bevezetés a bash programozásba HOGYAN</title>
    <author>Mike G <tt/mikkey at dynamo.com.ar/</author>
    <date> 
	2000. július 27.
    </date>
    <abstract> 
    Ezen dokumentum célja, hogy bevezessen az alap- illetve középszintű
    shell szkript írásba. A dokumentum nem egy
    minden részletre kiterjedő leírás (ez a címéből is kitűnik). Én nem vagyok se
    profi shell programozó, se guru. Azért döntöttem úgy, hogy
    megírom ezt a HOGYANt, mert sokat tanulhatok belőle és talán másoknak is
    hasznára válhat. Minden visszajelzésért hálás vagyok, különösképpen, ha
    folt (patch) formájában küldöd el. :)
    </abstract>

<!-- Table of contents -->
<toc>

<!-- Requisites -->
<sect>
Bevezetés


<sect1>
A dokumentum legújabb változata

<p>
     A dokumentum legújabb változata megtalálható a
     <url url="http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO.html"
     name="http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO.html">
     honlapon


     </sect1>

     <sect1>
     Szükséges alapok
          <p> Jól jöhet, ha ismered a GNU/Linux rendszerek parancssorát, és
	  hasznos, ha tisztában vagy az alapvető programozási elvekkel. Noha ez nem egy
	  programozásba bevezető leírás, sok ilyet is megpróbálok majd bemutatni.
          <p>
     </sect1>
     <sect1>
     A dokumentum használata
          <p> Ez a dokumentum a következő esetekben lehet hasznos:
	  <itemize>
	      <item> Már tudsz valamennyire programozni, és szeretnél végre
	      shell szkripteket írni.
	      <item> Van valami halvány fogalmad a shell programozásról, és
	      szeretnél többet megtudni róla.
	      <item> Látni akarsz pár shell szkriptet és némi magyarázatot,
	      hogy hozzáláthass sajátod megírásához.
	      <item> DOS/Windows rendszerről jössz/jöttél és "batch"
	      programokat akarsz írni.
	      <item> Annyira pedál vagy, hogy már
	      minden létező HOGYANt elolvastál.
	  </itemize>
     </sect1>
     <sect1>Magyar fordítás
          <p> A magyar fordítást <url url="mailto:    Kovacs.Ferenc.5[kukac]stud.u-szeged[pont]hu" name=" Kovács Ferenc"> készítette (2004.06.18). A lektorálást <url url="mailto: dacas[kukac]freemail[pont]hu" name="Daczi László"> végezte el (2004.06.20). A dokumentum legfrissebb változata megtalálható a <url url="http://tldp.fsf.hu/" name="Magyar Linux Dokumentációs Projekt"> honlapján. A dokumentum fordítása a <url url="http://www.u-szeged.hu/" name="Szegedi Tudományegyetem"> <url url="http://www.inf.u-szeged.hu/~havasi/opensource/" name="nyílt forráskódú szoftverfejlesztés speciálkollégium">ának segítségével valósult meg.
</sect>

<!-- Very simple Scripts -->
<sect>
Egyszerű szkriptek

    <p> Ez a HOGYAN megpróbál útmutatóként szolgálni a shell
    szkriptek megismeréséhez. A témát gyakorlati oldalról, példákon keresztül
    közelítjük meg.
    <p> Az ebben a részben található néhány példa remélhetőleg segít majd
    megérteni pár alapvető módszert.

    <sect1>
    A szokásos hello world szkript

        <!-- __TO-DO__
	someone suggested using this instead of the line numbering
	but it doesn't work on verion 1.0.9
	<pre></pre>
	-->
	<p>
	<tscreen><verb>
	  #!/bin/bash
	  echo Hello World
	</verb></tscreen>
	<p>
	<p> A szkript csak két sorból áll.
        Az elsőben jelezzük a rendszernek, hogy melyik
        programot használja a szkript futtatásához.
        <p> A másodikban pedig kiírjuk a "Hello World" szöveget a terminálra.
	<p> Ha a képernyőn a <it>./hello.sh: Command not found.</it> vagy ehhez
	hasonló üzenet jelenik meg, akkor valószínűleg az első sorban lévő
	"#!/bin/bash" lesz a ludas. A hiba javításához módosítsd az első sort
	úgy, hogy az a bash tényleges elérési útvonalát tartalmazza. Az útvonal
        lekérésére használható a "whereis bash" parancs, vagy olvasd el
	"A bash felkutatása" című fejezetet.
    </sect1>
    <sect1>
    Egy nagyon egyszerű backup szkript
        <p>
	<tscreen><verb>
	#!/bin/bash
	tar -cZf /var/my-backup.tgz /home/me/
	</verb></tscreen>
        <p> Ebben a szkriptben, az előzőtől eltérően, nem szöveget jelenítünk meg a
	képernyőn, hanem a felhasználó "home" könyvtárában lévő fájlokat
	összefűzzük egyetlen tar fájlba. Ez csak a példa kedvéért szerepel most
	itt, később egy sokkal használhatóbb backup szkriptet is bemutatunk.
    </sect1>
</sect>

<!-- Redirection -->
<sect>
Az átirányításról

	<sect1>
	Elmélet és gyors útbaigazítás
	<p> Három fájlleíró van: stdin, stdout és stderr (std=standard).

	<p>Alapvetően a következők tehetők meg:
	<enum>
	<item> stdout fájlba irányítása
	<item> stderr fájlba irányítása
	<item> stdout stderr-be irányítása
	<item> stderr stdout-ba irányítása
	<item> stderr és stdout fájlba irányítása
	<item> stderr és stdout stdout-ba irányítása
	<item> stderr és stdout stderr-be irányítása
	</enum>
	Az 1 az stdout, a 2 az stderr (a 0 pedig az stdin
	- a ford.).
	<p> Egy kis magyarázat, hogyan is kell mindezt érteni: a less paranccsal
        meg tudod nézni mind az stdout "tartalmát" (ami a bufferen marad), mind
	az stderr-ét, ami a képernyőn jelenik meg, de törlődik, amint olvasni
	próbálod a buffert.
	</sect1>

	<sect1>
	Példa: az stdout fájlba irányítása
	<p> Ennek hatására a program kimenete fájlba íródik.
	<tscreen><verb>
	ls -l > ls-l.txt
	</verb></tscreen>
        Itt létrejön az "ls-l.txt" nevű fájl, melynek tartalma meg fog egyezni
	azzal, amit az "ls -l" parancs futtatásakor a képernyőn látnál.
	</sect1>

	<sect1>
	Példa: az stderr fájlba irányítása
	<p> Hatására a program stderr kimenete fájlba íródik.
	<tscreen><verb>
	grep da * 2> grep-errors.txt
	</verb></tscreen>
        Itt is létrejön a "grep-errors.txt" nevű fájl, melynek tartalma a "grep
	da *" parancs stderr kimenetével fog megegyezni.
	</sect1>

	<sect1>
	Példa: az stdout stderr-be történő irányítása
	<p> Ennek hatására a program stderr kimenetére lesznek írva az stdout-ra
	küldött adatok is.
	<tscreen><verb>
	grep da * 1>&2
	</verb></tscreen>
	Itt a parancs stdout kimenete az stderr-re lesz elküldve, ahogy ezt
	már bizonyára észrevetted.
	</sect1>

	<sect1>
	Példa: az stderr stdout-ba történő irányítása
	<p> Most a program stderr kimenete az stdout-nak megfelelő fájlleíróba
	lesz írva.
	<tscreen><verb>
	grep * 2>&1
	</verb></tscreen>
        Itt az stderr-ra küldött adatok is az stdout-on jelennek meg. Ha ezt egy
	csővel (pipe) összekötöd a less programmal láthatod, hogy azok a sorok, amik
	normális esetben eltűnnének (mivel az stderr-ra írtuk őket), most
	megmaradnak (hiszen az stdout-ra lettek irányítva).
	</sect1>

	<sect1>
	Példa: az stderr és stdout fájlba irányítása
	<p> Ebben az esetben a program minden kimenete fájlba kerül. Ez néha
	hasznos lehet például a cron bejegyzések esetén, ha egy programot
	teljes csöndben akarsz futtatni.
	<tscreen><verb>
	rm -f $(find / -name core) &> /dev/null
	</verb></tscreen>
        Ez (gondolva itt a cron bejegyzésekre) minden könyvtárból kitörli a "core"
	nevű fájlokat. Fontos tisztában lenned azzal, hogy egy program
	pontosan mit is csinál, mielőtt "megszünteted" a kimenetét.
	</sect1>
<!--
redirect stderr and stdout to stdout
redirect stderr and stdout to stderr
-->



<!--
	<sect1>
	Sample:
	<p> This will
	<tscreen><verb>
	command
	</verb></tscreen>
	Explanation
	</sect1>
-->

</sect>

<!-- pipes -->
<sect>
Csövek (pipe)
	<p> Ebben a fejezetben a csövek használatának egy egyszerű és hasznos
	módját ismertetjük, valamint elmondjuk hol lehet szükséged rájuk.

	<sect1>
	A csövek és azok használata
		<p> A csövek olyan egyszerű eszközök, melyek lehetővé teszik,
		hogy egy program bemenetét egy másik program kimenetéről vegye.
	</sect1>


	<sect1>
	Példa: csövek és a sed
	<p> Ez a csövek használatának egy nagyon egyszerű módja.
	<tscreen><verb>
	ls -l | sed -e "s/[aeio]/u/g"
	</verb></tscreen>
	Itt a következő történik: először az ls -l parancs végrehajtódik, de a
	kimenete nem lesz kiírva a képernyőre, hanem el lesz küldve a sed
	programnak, ami ezt bemenetként értelmezi és ebből előállítja saját
	kimenetét.
	</sect1>

	<sect1>
	Példa: az ls -l *.txt parancs másként
	<p> A következő parancs minden bizonnyal sokkal bonyolultabb, mint a
	szokásos ls -l *.txt, de a csövek tulajdonságainak illusztrálására jó
	példa. A gyakorlatban ilyen listázási problémák megoldására lehetőleg
	ne használjunk csöveket.
	<tscreen><verb>
	ls -l | grep "\.txt$"
	</verb></tscreen>
	Itt az ls -l program kimenete el lesz küldve a grep programnak, ami
	kiírja azokat a sorokat, melyek illeszkednek a "\.txt$" reguláris
	kifejezésre.
	</sect1>



<!--
	<sect1>
	Sample:
	<p> This will
	<tscreen><verb>
	command
	</verb></tscreen>
	Explanation
	</sect1>
-->


</sect>




<!-- Variables -->
<sect>
Változók

    <!-- Dry Theory -->
        <p> Ugyanúgy használhatsz változókat, mint bármely más programozási
	nyelvben. Adattípusok nincsenek. Egy bash változó tárolhat számot,
	karaktert és karakterekből álló sztringet.
	<p> A változókat nem kell külön deklarálni, a rájuk való hivatkozáskor
	automatikusan létrejönnek.


    <!-- Samples -->
        <sect1>
	Példa: Hello World! változókkal
            <p>
	    <tscreen><verb>
	    #!/bin/bash
	    STR="Hello World!"
	    echo $STR
	    </verb></tscreen>

	    <p> A második sorban létrejön egy STR nevű változó, melynek értéke
	    a "Hello World!" (sztring) lesz. Ezután a változó neve elé tett "$"
	    jellel tudjuk elérni annak értékét. Jegyezd meg (és próbáld is
	    ki), hogy ha nem használod a "$" jelet, a program kimenete más lesz
	    és valószínűleg nem az, amit szeretnél.
	</sect1>

        <sect1>
	   Példa: Egyszerű backup szkript (kicsivel jobb változat)
	   <p>
	   <tscreen><verb>
	   #!/bin/bash
	   OF=/var/my-backup-$(date +%Y%m%d).tgz
	   tar -cZf $OF /home/me/
	   </verb></tscreen>
	   <p> Ez a szkript felvet egy másik dolgot is. De mindenek előtt
	   tisztában kell lenned a változók létrehozásával, az értékadással
	   kapcsolatos dolgokkal (ez a második sorban látható). Most vegyük
	   szemügyre a "$(date +%Y%m%d)" kifejezést. Ha futtatod a szkriptet
	   a zárójelek közti parancs is lefut, létrehozva kimenetét.

	   <p> Azt is vegyük észre, hogy a kimeneti fájl neve minden nap más és más
	   lesz, a date parancs formátum-kapcsolóinak (+%Y%m%d) köszönhetően.
	   Ezt módosíthatod más formátum megadásával.
	   <p> Még néhány példa:
	   <p> echo ls
	   <p> echo $(ls)
	</sect1>

	<sect1>
	Lokális változók

	<p> Lokális változókat a <it/local/ kulcsszóval tudunk létrehozni.

	<tscreen><verb>
		#!/bin/bash
		HELLO=Hello
		function hello {
			local HELLO=World
			echo $HELLO
		}
		echo $HELLO
		hello
		echo $HELLO
	</verb></tscreen>
	<p> Ennek a példának elégnek kell lennie, hogy bemutassa a
	lokális változók használatát.
	</sect1>

</sect>

<!-- Conditionals -->
<sect>
Feltételes utasítások

    <p> A feltételes utasítások segítségével dönthetünk, hogy végrehajtunk-e
    valamit vagy nem. A döntés itt egy kifejezés kiértékeléséből áll.

    <!-- Dry Theory -->
    <sect1>
    Elmélet
        <p> A feltételes utasításoknak több formája is van. A legalapvetőbb a
	következő: <bf>if</bf> <it/kifejezés/ <bf>then</bf> <it/utasítás/,
	ahol az "utasítás" csak akkor kerül végrehajtásra, ha a kifejezés,
	kiértékelése után igazat ad vissza. Például a "2<1" kifejezés kiértékelés
	utáni értéke hamis, míg a "2>1" esetén igaz.

	<p> A másik eset:
	<bf/if/ <it/kifejezés/
	<bf/then/ <it/utasítás1/ <bf/else/ <it/utasítás2/.
	Az "utasítás1" akkor hajtódik végre, ha a kifejezés igaz, egyéb esetben
	az "utasítás2" kerül végrehajtásra.
	<p> A feltételes utasítás egy másik formája:
	<bf/if/ <it/kifejezés1/
	<bf/then/ <it/utasítás1/
	<bf/else if/ <it/kifejezés2/ <bf/then/ <it/utasítás2/
	<bf/else/ <it/utasítás3/.
	Ebben az esetben csak az
	"ELSE IF 'kifejezés2' THEN 'utasítás2'" részt adtuk hozzá, így az
        utasítás2 akkor lesz végrehajtva, ha a kifejezés2 kiértékelés utáni
	értéke igaz. A többit már magad is el tudod képzelni (nézd meg az
	előző formákat).
	<p> Pár szó a szintaxisról:
	<p> Bash-ban az "if" szerkezetek a következőképp néznek ki:
	<p> if [kifejezés];
	<p> then
	<p>    a "kifejezés" igaz volta esetén végrehajtódó kód
	<p> fi
    </sect1>
    <!-- Samples -->
        <sect1>
	Példa: alapvető feltételes utasítás (if ... then)
	    <p>
	    <tscreen><verb>
	    #!/bin/bash
	    if [ "foo" = "foo" ]; then
	       echo a feltétel igaz
	    fi
	    </verb></tscreen>
	    <p> A szögletes zárójelbe tett kifejezés igaz értéke esetén végrehajtódó
	    kód a "then" kulcsszó után és a "fi" kulcsszó előtt helyezkedik el. A
	    "fi" kulcsszó jelzi a feltételesen végrehajtandó kód végét.
	</sect1>
	<sect1>
	Példa: alapvető feltételes utasítás (if ... then ... else)
	    <p>
	    <tscreen><verb>
	    #!/bin/bash
	    if [ "foo" = "foo" ]; then
	       echo a feltétel igaz
	    else
	       echo a feltétel hamis
	    fi
	    </verb></tscreen>
	</sect1>
	<sect1>
        Példa: Változók és feltételes utasítások
	    <p>
	    <tscreen><verb>
	    #!/bin/bash
	    T1="foo"
	    T2="bar"
	    if [ "$T1" = "$T2" ]; then
	        echo a feltétel igaz
	    else
	        echo a feltétel hamis
	    fi
	    </verb></tscreen>
	</sect1>
<!--
	<sect1>
	Sample: testing if a file exists
	    <p> one more thank to mike
	    <tscreen><verb>
	    #!/bin/bash
	    FILE=~/.basrc
	    if [ -f $FILE ]; then
	        echo file $FILE exits
	    else
	        echo file not found
	    fi
	    if [ 'test -f $FILE']
	    </verb></tscreen>
	</sect1>
-->

</sect>

<!-- Loops : for, while and until -->
<sect>
Ciklusok (for, while és until)
    <!-- Dry Theory -->

    <p> Ebben a részben a for, while és until ciklusokról lesz szó.
    <p> A <bf/for/ ciklus egy kicsit eltér a más nyelvekben megszokottaktól.
    Alapvetően egy sztringekben szereplő szavak halmazának feldolgozására
    használjuk.
      <p> A <bf/while/ ciklus addig ismétli a ciklusmagot, amíg a ciklusfeltétel
      hamissá nem válik (vagy ki nem ugrunk a ciklusmagból a break utasítással).
      <p> Az <bf/until/ ciklus tulajdonképpen azonos a while ciklussal, a különbség
      csupán annyi, hogy az ismétlés addig folytatódik, amíg a feltétel hamis.
      <p> Ha gyanús volt számodra, hogy a while és az until ciklusok mennyire
      hasonlók, akkor igazad volt.
    <!-- Samples -->
    <sect1>
    Példa for ciklusra
        <p>
	<tscreen><verb>
        #!/bin/bash
        for i in $( ls ); do
            echo elem: $i
        done
        </verb></tscreen>
        <p>
        <p> A második sorban deklaráltunk egy "i" nevű változót, ami majd sorra
        felveszi a $( ls ) sztring különböző értékeit.
        <p> A harmadik sor szükség esetén méretesebb is lehet, vagy több sor is
	szerepelhet a ciklusmagban a done (4. sor) kulcsszó előtt.
        <p> A "done" (4. sor) jelzi, hogy a $i értéket használó kódrészlet
        befejeződött. Innentől kezdve a $i új értéket vehet fel.
        <p> Ennek a szkriptnek így nem sok értelme van. A for ciklus használatának
	egy sokkal hasznosabb módja, ha az előző példánál csak bizonyos fájlokat
        vizsgálunk.
    <p>
    </sect1>
	<sect1>
	C-szerű for ciklus
	<p> Fiesh tanácsára került ide ez a példa, ami egy C/Perl-szerű for
	ciklust mutat be.
	<tscreen><verb>
	#!/bin/bash
	for i in `seq 1 10`;
	do
		echo $i
	done
	</verb></tscreen>
	</sect1>
    <!-- while -->
    <sect1>
    While példa
         <p> <tscreen><verb>
         #!/bin/bash
         COUNTER=0
         while [  $COUNTER -lt 10 ]; do
             echo A számláló értéke: $COUNTER
             let COUNTER=COUNTER+1
         done
         </verb></tscreen>
	 <p>
	 <p> Ez a szkript a jól ismert "for" ciklust utánozza (C, Pascal, perl, stb.).
    </sect1>
    <!-- until -->
    <sect1>
    Until példa
         <p> <tscreen><verb>
         #!/bin/bash
         COUNTER=20
         until [  $COUNTER -lt 10 ]; do
             echo COUNTER $COUNTER
             let COUNTER-=1
         done
	 </verb></tscreen>
    </sect1>
</sect>

<!-- Functions -->
<sect>
Függvények
     <p> Mint a legtöbb programozási nyelvben itt is használhatunk függvényeket
     a kód logikailag összetartozó részeinek csoportosítására, vagy ha csak áldozni
     szeretnénk a rekurzió virtuális oltára előtt (azaz ha rekurzív függvényeket akarunk írni).
     <p> A függvénydeklaráció csupán ennyiből áll: function my_func { my_code }.
     <p> A függvény hívása pedig ugyanúgy történik, mint bármelyik program esetén, csak leírjuk a nevét.
     <p>
     <sect1>
     Példa függvényekre
           <p> <tscreen><verb>
	   #!/bin/bash
	   function quit {
	       exit
	   }
	   function hello {
	       echo Hello!
	   }
	   hello
	   quit
	   echo foo
	   </verb></tscreen>
	   <p> A 2-4 sorok tartalmazzák a "quit", az 5-7 sorok pedig a "hello"
	   függvényt. Ha nem teljesen világos számodra, hogy mit is csinál a szkript,
	   próbáld ki!
	   <p> Megjegyzendő, hogy a függvénydeklaráció sorrendje tetszőleges.
	   <p> Amikor lefuttatjuk a szkriptet látjuk, hogy először a "hello", majd a "quit"
	   függvények hívódnak meg és a program sohasem éri el a 10. sort (echo foo).
     </sect1>

     <sect1>
     Példa paraméteres függvényekre
           <p> <tscreen><verb>
		#!/bin/bash
		function quit {
 		   exit
		}
		function e {
		    echo $1
		}
		e Hello
		e World
		quit
		echo foo

	   </verb></tscreen>
	   <p> Ez a szkript nagyrészt megegyezik az előzővel. A fő különbség az
	   "e" nevű függvényben rejlik, ami nem csinál mást, mint kiírja az első
	   átvett argumentumot. A függvényeknél szereplő argumentumok ugyanúgy
	   kezelhetők, mint a szkriptnek átadott argumentumok.
     </sect1>


</sect>


<!-- User interfaces -->
<sect>
Felhasználói felületek
     <!-- Simple menus with select -->
     <sect1>
     Egyszerű menü a "select" használatával
	   <p>
	   <tscreen><verb>
	   #!/bin/bash
	   OPTIONS="Hello Quit"
	   select opt in $OPTIONS; do
	       if [ "$opt" = "Quit" ]; then
	   	echo done
	   	exit
	       elif [ "$opt" = "Hello" ]; then
	   	echo Hello World
	       else
	   	clear
	   	echo rossz válasz
	       fi
	   done
	  </verb></tscreen>
           <p> Ha lefuttatod a szkriptet láthatod, hogy ez a programozók álma,
	   ha szöveges menükről van szó. Biztos észrevetted, hogy ez nagyon
	   hasonlít a "for" ciklusra. Csak itt ahelyett, hogy minden $OPTIONS
	   elemre egyszerűen végrehajtanánk a ciklust, mindig "megállítjuk" a
	   felhasználót.
	   <p>
     </sect1>
    <!-- Using the command line -->
    <sect1>
    A parancssor használata
         <p>
	 <tscreen><verb>
	  #!/bin/bash
          if [ -z "$1" ]; then
              echo használat: $0 könyvtárnév
              exit
          fi
          SRCD=$1
          TGTD="/var/backups/"
          OF=home-$(date +%Y%m%d).tgz
          tar -cZf $TGTD$OF $SRCD
	 </verb></tscreen>
	 <p>
	 <p> Világosnak kell lennie számodra annak, hogy ez a szkript mit csinál. Az
	 első feltételben szereplő kifejezéssel megnézzük, hogy a program
	 kapott-e argumentumot ($1). Ha nem, kilépünk, és egy használati
	 útmutatót jelenítünk meg a felhasználónak. A program többi részének
	 ezen a ponton már tisztának kell lennie.
    </sect1>

</sect>

<!-- Misc -->
<sect>
Egyebek
    <!-- Reading user input  -->
    <sect1>
    Adatok bekérése felhasználótól: read
         <p> Sok esetben szükség lehet arra, hogy adatokat kérjünk be a
	 felhasználótól. Erre számos lehetőségünk van, melyek közül egy a
	 következő:
	<tscreen><verb>
		#!/bin/bash
		echo Kérlek add meg a neved
		read NAME
		echo "Hi $NAME!"
	</verb></tscreen>
	<p> A read segítségével egyszerre több adatot is be tudsz olvasni. A
	következő példa ezt tisztázza.
	<tscreen><verb>
		#!/bin/bash
		echo Kérlek add meg a vezeték- és keresztneved
		read FN LN
		echo "Hi! $LN, $FN !"
	</verb></tscreen>

    </sect1>

    <!-- Arithmetic evaluation  -->
    <sect1>
    Aritmetikai kifejezések kiértékelése
         <p> A parancssorba (vagy a shell-be) írd be a következőt:
	 <p> echo 1 + 1
	 <p> Ha "2"-t vártál eredményül bizonyára csalódott vagy. De mi van
	 akkor, ha azt szeretnéd, hogy a bash ki is értékelje a számokat? A
	 megoldás a következő:
	 <p> echo $((1+1))
	 <p> Ez már sokkal logikusabb kimenetet ad. Így kell egy aritmetikai
	 kifejezést kiértékelni. Ugyanezt az eredményt kapod a következővel:
	 <p> echo $[1+1]
	 <p>
	 <p> Ha törtekre vagy más matematikai jellegű dolgokra van szükséged,
	 vagy egyszerűen csak ezt szeretnéd használni, akkor bc-vel is kiértékelheted
	 az aritmetikai kifejezéseket.
	 <p> Ha beírom a parancssorba, hogy "echo $[3/4]", akkor 0-t kapok,
         mivel a bash csak egészekkel dolgozik. Az "echo 3/4|bc -l" parancsra
	 viszont már helyes eredményt ad, azaz 0.75-öt.
    </sect1>


    <sect1>
    A bash felkutatása
        <p> Mike levele nyomán (nézd meg a köszönetnyilvánítást):
        <p> Eddig mindig a "#!/bin/bash" formát használtuk, most itt van pár példa arra,
        hogyan tudhatod meg a bash konkrét elérési útját.
        <p> A "locate bash" az egyik legjobb módszer erre a feladatra, de nem minden rendszeren van locate.
        <p> A gyökérből kiadott "find ./ -name bash" legtöbbször működik.
        <p> A lehetséges helyek, ahol nézelődhetsz:
        <p>         ls -l /bin/bash
        <p>         ls -l /sbin/bash
        <p>         ls -l /usr/local/bin/bash
        <p>         ls -l /usr/bin/bash
        <p>         ls -l /usr/sbin/bash
        <p>         ls -l /usr/local/sbin/bash
        <p> (Most kapásból nem jut több eszembe...  A legtöbb rendszeren
        <p> ezen könyvtárak valamelyikében lesz).
	<p> Vagy megpróbálhatod a "which bash" parancsot is.
   </sect1>

    <!-- Capturing a commands output  -->
    <sect1>
    Program visszatérési értékének kiderítése
        <p> Bash-ban a programok visszatérési értéke egy speciális változóban tárolódik, melynek neve $?.
	<p> A következő példa bemutatja, hogyan deríthetjük ki egy program
	visszatérési értékét. Feltételezem, hogy a <it/dada/ nevű könyvtár nem
	létezik. (Ez szintén Mike javaslatára került ide.)
	<tscreen><verb>
	#!/bin/bash
	cd /dada &> /dev/null
	echo rv: $?
	cd $(pwd) &> /dev/null
	echo rv: $?
	</verb> </tscreen>
    </sect1>


    <!-- Capturing a commands output  -->
    <sect1>
    Parancs kimenetének tárolása
         <p> A következő szkript listázza az összes táblát az összes adatbázisból (felteszem, hogy MySQL-t használsz).
	Megváltoztathatod a "mysql" parancsot úgy, hogy valódi felhasználónevet és jelszót használsz.
	<tscreen><verb>
	#!/bin/bash
	DBS=`mysql -uroot  -e"show databases"`
	for b in $DBS ;
	do
	        mysql -uroot -e"show tables from $b"
	done
	</verb></tscreen>
    </sect1>

    <!-- Multiple source files -->
    <sect1>
    Több forrásfájl használata
        <p> A "source" parancs segítségével több fájlt is használhatsz egyszerre.
	<p> __TO-DO__
    </sect1>
</sect>


<!-- Tables -->
<sect>
Táblázatok
    <!-- String operators -->
    <sect1>
    Sztring összehasonlító operátorok

    <p> (1) s1 = s2
    <p> (2) s1 != s2
    <p> (3) s1 < s2
    <p> (4) s1 > s2
    <p> (5) -n s1
    <p> (6) -z s1
    <p>
    <p> (1) s1 megegyezik s2-vel
    <p> (2) s1 nem egyezik meg s2-vel
    <p> (3) __TO-DO__
    <p> (4) __TO-DO__
    <p> (5) s1 nem nulla (egy vagy több karakterből áll)
    <p> (6) s1 nulla
    </sect1>

	<sect1>
	Példák sztingek összehasonlítására
	<p> Két sztring összehasonlítása.
	<tscreen><verb>
	#!/bin/bash
	S1='string'
	S2='String'
	if [ $S1=$S2 ];
	then
	        echo "S1('$S1') nem egyenlő S2('$S2')-vel"
	fi
	if [ $S1=$S1 ];
	then
	        echo "S1('$S1') egyenlő S1('$S1')-vel"
	fi
	</verb></tscreen>
	<p> Most idézek egy részt Andreas Beck leveléből, az <it/if [ $1 = $2 ]/
	alakú utasításokkal kapcsolatban.
	<p> Nem túl jó ötlet a fenti példában is látható módszert használni, mert
	ha a $S1 vagy a $S2 üres, értelmezési hibát kapunk. Helyette használjuk
	inkább az x$1=x$2 vagy a "$1"="$2" formát.

	</sect1>

    <!-- Arithmetic operators -->
    <sect1>
    Aritmetikai operátorok
    <p> +
    <p> -
    <p> *
    <p> /
    <p> % (maradék)
    </sect1>

    <!-- Arithmetic relational operators -->
    <sect1>
    Aritmetikai relációs operátorok
    <p> -lt (<)
    <p> -gt (>)
    <p> -le (<=)
    <p> -ge (>=)
    <p> -eq (==)
    <p> -ne (!=)
    <p> A C programozók egyszerűen össze tudják vetni ezen operátorokat a
    zárójelek közt megadottakkal.
    </sect1>


    <!-- Useful commands  -->
    <sect1>
    Hasznos parancsok
         <p> Ezt a részt Kees újraírta (nézd meg a köszönetnyilvánítást...).
	 <p>  Néhány ezek közül a programok közül egy komplett programozási nyelvet takar.
	Ezen parancsok esetén csak az alapokat ismertetjük. Ha részletes leírásra
        is szükséged van nézd meg a parancsok kézikönyv oldalait (man pages).

	<bf/sed/ (folyam szerkesztő)

   	<p> A sed egy nem interaktív szerkesztőprogram. Ez azt jelenti, hogy a fájlok
	módosítása nem úgy megy, hogy mozgatod a kurzort a képernyőn. Itt szerkesztő
	utasításokból álló szkripteket használunk és egy fájlnevet, amit szerkeszteni
	akarunk. A sed tulajdonképpen egy szűrőnek is felfogható. Nézzük az alábbi
        példákat:

   	<tscreen><verb>
	$sed 's/mit_cseréljek/mire_cseréljem/g' /tmp/dummy
	</verb></tscreen>

   	<p> A sed kicseréli a "mit_cseréljek" szöveget a "mire_cseréljem" szöveggel,
        és a bemenetét a /tmp/dummy fájlból veszi. A végeredmény az stdout-ra lesz
	küldve (ami alapesetben a konzol), de ha a sor végéhez írod, hogy "> fájlnév",
	akkor a sed kimenetét a "fájlnév" nevű fájlba küldi.

	<tscreen><verb>
   	$sed 12, 18d /tmp/dummy
	</verb></tscreen>

   	<p> A sed, a 12. és 18. sorok közti rész kivételével kiírja a fájl
	tartalmát. Az eredeti fájl nem változik.

	<bf/awk/ (fájlok módosítása, szöveg kinyerése és szerkesztése)

   	<p> Az AWK-nak számos implementációja létezik (a legismertebbek a GNU-s
	gawk és az ún. "új awk", a mawk). Az alapelv egyszerű: az AWK mintát
	keres és minden illeszkedő mintára végrehajt valamilyen műveletet.
   	<p> Megint létrehoztam egy dummy nevű fájlt, ami a következő sorokból áll:
	<p> <it/"test123/
   	<p> <it/test/
	<p> <it/tteesstt"/

   	<tscreen><verb>
	$awk '/test/ {print}' /tmp/dummy
	</verb></tscreen>
   	<p> test123

   	<p> test

   	<p> A minta, amit az AWK keres, a "test". Ha a /tmp/dummy fájlban talált
	egy sort, amiben szerepelt a "test" szó, akkor végrehajtotta rá a "print"
        műveletet.

   	<tscreen><verb>
	$awk '/test/ {i=i+1} END {print i}' /tmp/dummy
	</verb></tscreen>

   	<p> 3

   	<p> Ha sokféle mintára keresel, cseréld ki az idézőjelek közti szöveget
	"-f file.awk"-ra és a mintákat, végrehajtandó tevékenységeket írd a
	"file.awk" nevű fájlba.

   	<bf/grep/ (a keresési mintára illeszkedő sorok kiírása)

   <p> Az előző fejezetekben már jó néhány grep parancsot láttunk, amelyek az
   illeszkedő sorokat írták ki. De a grep többre is képes.
   	<tscreen><verb>
   	$grep "ezt keressük" /var/log/messages -c
	</verb></tscreen>
   <p> 12
   <p> Az "ezt keressük" szöveg 12-szer szerepelt a /var/log/messages nevű fájlban.

   <p> [Jó, ez csak egy kitalált példa, a /var/log/messages meg lett buherálva. :-)]

   <bf/wc/ (sorok, szavak, bájtok megszámolása)

   <p> A következő példában mást kapunk, mint amit várunk. A dummy nevű fájl,
   amit most használunk, a következő szöveget tartalmazza:
       	<it/"bash bevezetés/
     	<it/ HOWTO teszt fájl"/

   <tscreen><verb>
	$wc --words --lines --bytes /tmp/dummy
	</verb></tscreen>

   <p> 2 5 34 /tmp/dummy

   <p> A wc nem foglalkozik a paraméterek sorrendjével. Mindig egy előre megadott
   sorrendben írja ki őket, amint azt te is láthatod: (sorok)(szavak)(bájtok)(fájlnév).

   <bf/sort/ (szöveges fájl sorainak rendezése)

   <p> Most a dummy fájl a következőket tartalmazza:
   <p> <it/"b/
   <p> <it/c/
   <p> <it/a"/
   	<tscreen><verb>
	$sort /tmp/dummy
	</verb></tscreen>

   <p> A kimenet kábé így néz ki:

   <p> <it/a/
   <p> <it/b/
   <p> <it/c/

   <p> A parancsok nem lehetnek ilyen egyszerűek :-)
   
   <bf/bc/ (egy számológépes programozási nyelv)

   <p> A bc a parancssorból kapja meg a számítási feladatokat (fájlból, nem pedig átirányítás vagy cső útján),
   esetleg egy felhasználói felületről. A következőkben példákon keresztül
   bemutatunk néhány parancsot.
   <p> A bc-t a -q paraméterrel indítom, hogy ne írja ki az üdvözlő szöveget.

   	<tscreen><verb>
   $bc -q
	</verb></tscreen>

   <p> <it/1 == 5/
   <p> <it/0/
   <p> <it/0.05 == 0.05/
   <p> <it/1/
   <p> <it/5 != 5/
   <p> <it/0/
   <p> <it/2 ^ 8/
   <p> <it/256/
   <p> <it/sqrt(9)/
   <p> <it/3/
   <p> <it/while (i != 9) {/
   <p> <it/i = i + 1;/
	<p> <it/print i/
   <p> <it/}/
   <p> <it/123456789/
   <p> <it/quit/

   <bf/tput/ (terminál inicializálására vagy a terminfo adatbázis lekérdezésére)

   <p> Egy kis példa a tput képességeinek demonstrálására:
   	<tscreen><verb>
	$tput cup 10 4
	</verb></tscreen>
   <p> A kurzor a (y10,x4)-es pozícióban jelenik meg.
   	<tscreen><verb>
	$tput reset
	</verb></tscreen>
   <p> Törli a képernyőt, és a kurzor az (y1,x1) pozícióba kerül. Az (y0,x0) a bal felső sarok koordinátája.
   	<tscreen><verb>
	$tput cols
	</verb></tscreen>
   <it/80/
   <p> Az x tengely irányában maximálisan elhelyezhető karakterek száma.
   <p> Nagyon ajánlott, hogy legalább ezen programok használatával tisztában
       legyél. Millió olyan kis program van, amikkel csodákra lehetsz képes a
       parancssorban.
   <p> [Néhány példa kézikönyv oldalból vagy GYIK-ből származik.]
    </sect1>
</sect>


<!-- More Scripts -->
<sect>
Még néhány szkript
     <sect1>
     Parancs végrehajtása a könyvtárban lévő összes fájlra
     <p>
     </sect1>
     <sect1>
     Példa: egyszerű backup szkript (egy kicsivel jobb verzió)
	   <p>
	   <tscreen><verb>
	    #!/bin/bash
	    SRCD="/home/"
	    TGTD="/var/backups/"
	    OF=home-$(date +%Y%m%d).tgz
	    tar -cZf $TGTD$OF $SRCD
	   </verb></tscreen>
	   <p>
     </sect1>
     <sect1>
     Fájl átnevező program
          <p>
	  <tscreen><verb>

             #!/bin/sh
             # renna: egyszerre több fájl átnevezése különböző szabályok szerint
             # írta: Felix Hudson (2000. január)

             # először is megnézzük, hogy a program milyen "üzemmódban" van
             # ha az első paraméter ($1) alapján valamelyik feltétel teljesül végrehajtjuk
             # a hozzá tartozó programrészt és kilépünk

             # előtag (prefix) szerint történő átnevezés?
             if [ $1 = p ]; then

             # most megszabadulunk a módot tartalmazó változótól ($1) és a prefixtől ($2)
               prefix=$2 ; shift ; shift

             # megnézzük, adtak-e meg fájlnevet
             # ha nem, jobb ha nem csinálunk semmit, minthogy nemlétező fájlokat
             # nevezzünk át

               if [$1 = ]; then
                  echo "nem adtál meg fájlnevet"
                  exit 0
               fi

             # ez a for ciklus végigmegy a megadott fájlokon és mindet
             # egyenként átnevezi
               for file in $*
                 do
                 mv ${file} $prefix$file
               done

             # kilépünk a programból
               exit 0
             fi

             # utótag (suffix) szerinti átnevezés?
             # az ide tartozó rész tulajdonképpen megegyezik az előzővel
             # nézd meg az ottani megjegyzéseket
             if [ $1 = s ]; then
               suffix=$2 ; shift ; shift

                if [$1 = ]; then
                 echo "nem adtál meg fájlnevet"
                exit 0
                fi

              for file in $*
               do
                mv ${file} $file$suffix
              done

              exit 0
             fi

             # helyettesítéses átnevezés?
             if [ $1 = r ]; then

               shift

             # ezt a részt azért raktam bele, hogy ne tegyük tönkre a felhasználó egyik
             # állományát se, ha helytelenek a paraméterek
             # ez csak egy biztonsági intézkedés

               if [ $# -lt 3 ] ; then
                 echo "használat: renna r [kifejezés] [helyettesítés] fájlok... "
                 exit 0
               fi

             # továbblépünk a paraméterlistán
               OLD=$1 ; NEW=$2 ; shift ; shift

             # Ez a for ciklus végigmegy az összes fájlon amit a programnak átadtak,
             # és egyenként átnevezi őket a "sed" program segítségével.
             # A "sed" egyszerű parancssori program, ami értelmezi a bemenetet és
             # kicseréli a beállított kifejezést egy adott szövegre.
             # Mi itt a fájl nevét adjuk át neki (standard bemenetként), és kicseréljük
             # benne a kifejezésnek megfelelő szövegrészeket.

               for file in $*
               do
                 new=`echo ${file} | sed s/${OLD}/${NEW}/g`
                 mv ${file} $new
               done
             exit 0
             fi

             # Ha idáig eljutottunk, akkor semmi használhatót nem adtak át a programnak
             # ezért kiírjuk a felhasználónak, hogyan használja ezt a szkriptet.
             echo "használat:"
             echo " renna p [előtag] fájlok.."
             echo " renna s [utótag] fájlok.."
             echo " renna r [kifejezés] [helyettesítés] fájlok.."
             exit 0
             
             #ennyi!
             
	  </verb></tscreen>
     </sect1>
     <sect1>
     Átnevező program (egyszerű változat)
     <p>
     <tscreen><verb>
     #!/bin/bash
     # renames.sh
     # egyszerű átnevező program

     criteria=$1
     re_match=$2
     replace=$3
     
     for i in $( ls *$criteria* ); 
     do
         src=$i
	 tgt=$(echo $i | sed -e "s/$re_match/$replace/")
	 mv $src $tgt
     done
     </verb></tscreen>
     </sect1>
</sect>

<sect>
Ha gond van... (hibakeresés)
     <sect1>
     A bash meghívásának módjai
          <p> Jó dolog, ha az első sorban a következő szerepel:
	  <tscreen><verb>
	  #!/bin/bash -x
	  </verb></tscreen>
	  <p> Ennek hatására érdekes kimeneti információkat kaphatunk.
     </sect1>
</sect>

<sect>
A dokumentumról
     <p> Szabadon küldhetsz javaslatokat/hibajavításokat vagy bármi olyat, 
     amiről úgy gondolod, hogy érdekes és szívesen látnád a dokumentumban. 
     Megpróbálom majd olyan gyakran frissíteni a leírást, amilyen gyorsan csak
     tudom.
     <sect1>
     (nincs) garancia
          <p> A dokumentummal kapcsolatban semmiféle garancia nincs.
     </sect1>
     <sect1>
     Fordítások
     	<p> Olasz: by William Ghelfi (wizzy at tiscalinet.it) 
     		<url name="itt a cím" url="http://web.tiscalinet.it/penguin_rules">
     	<p> Francia: by Laurent Martelli 
		<url name="nincs cím" url="http://">
	<p> Koreai: Minseok Park 
		<url url="http://kldp.org" name="http://kldp.org">
	<p> Koreai: Chun Hye Jin 
		<url url="" name="ismeretlen">
	<p> Spanyol: ismeretlen 
		<url url="http://www.insflug.org" name="http://www.insflug.org">
     <p> Lehet, hogy több fordítás is van, de én nem tudok róla. Ha neked ilyen
     van, kérlek küldd el, hogy frissíthessem ezt a részt.
     </sect1>
     <sect1>
     Köszönet
     <p>
     <itemize>
     	<item> Azoknak, akik más nyelvekre fordították a dokumentumot (lásd: előző rész).
        <item> Nathan Hurstnek a sok hibajavításért.
	<item> Jon Abbottnak az aritmetikai kifejezések kiértékeléséhez fűzött megjegyzéseiért.
	<item> Felix Hudsonnak a <it/renna/ szkriptért
	<item> Kees van den Broeknek (számos hibajavításért és a "Hasznos parancsok" című fejezet újraírásáért)
	<item> Mikenak (pink), a bash felkutatásával és fájlok tesztelésével kapcsolatos javaslataiért.
	<item> Fieshnek, a ciklusokkal foglalkozó részben tett hasznos megjegyzéséért.
	<item> Lionnak, akinek javaslatára megemlítettünk egy gyakori hibát (./hello.sh: Command not found).
	<item> Andreas Becknek a hibajavításokért és megjegyzésekért.
     </itemize>
     </sect1>
	<sect1>
	Történet
	<p> Új fordítások és lényegi javítások.
	<p> A Kess által átírt hasznos parancsok rész hozzáadása.
	<p> Hibajavítások, javaslatok.
	<p> Példák a sztring összehasonlításhoz.
	<p> v0.8 Elhagyom a verziószámozást, rájöttem, hogy a dátum is elég.
	<p> v0.7 Számos hibajavítás és pár régi TO-DO rész megírása.
	<p> v0.6 Kisebb javítások.
	<p> v0.5 Az átirányítással foglalkozó rész hozzáadása.
	<p> v0.4 A volt főnökömnek köszönhetően a doksi eltűnt a régi helyéről, most
	a www.linuxdoc.org címen érhető el.
	<p> előtte: Nem emlékszem, nem használtam se rcs-t, se cvs-t. :(
	</sect1>

     <sect1>
     További források
          <p>
	  <p> Bevezetés a bash programozásba (BE alatt) 
	      <url url="http://org.laol.net/lamug/beforever/bashtut.htm"
		name="http://org.laol.net/lamug/beforever/bashtut.htm">
          <p> Bourne shell programozás
	      <url url="http://207.213.123.70/book/"
		name="http://207.213.123.70/book/">
		
    <sect1>
     További források magyarul
          <p>
	  <p>(Ezeket a forrásokat a lektor gyűjtötte össze.)
	  <p>
	  <p> Büki András: "UNIX/Linux héjprogramozás" (ISBN: 963 9301 10 8)
	  <p> Bourne shell programozás
	      <url url="http://www.inf.u-szeged.hu/~bmse/unix/unix3.html"
		name="http://www.inf.u-szeged.hu/~bmse/unix/unix3.html">
	  <p> Shell programozás
	      <url url="http://shell-script-programing.sync.hu/SHELL_PROGRAMOZAS.htm"
		name="http://shell-script-programing.sync.hu/SHELL_PROGRAMOZAS.htm">
	  <p> Shell programozás
	      <url url="http://www.fsz.bme.hu/~szebi/slides/U3/sld010.htm"
		name="http://www.fsz.bme.hu/~szebi/slides/U3/sld010.htm">
	  <p> Shell programozás
	      <url url="http://www.szabilinux.hu/ufi/10.html"
		name="http://www.szabilinux.hu/ufi/10.html">
     </sect1>
</sect>

</article>
