#!/usr/bin/tcsh
#-------------------------------------------------------------------------------
# tcshcode.sh                               (C) 2004-2011 T.Birnthaler OSTC GmbH
# Die Anweisungen der "csh/tcsh" ausprobieren.
# $Id: tcshcode.sh,v 1.5 2011/12/09 14:27:48 tsbirn Exp tsbirn $
#-------------------------------------------------------------------------------
# Die Shee-Bang-Zeile "#!/bin/tcsh" IMMER ab 1.Zeile/1.Spalte angeben
#-------------------------------------------------------------------------------
# Aufgrund des hohen Alters der Shell und ihrer Verwendung als interaktiver
# Kommandointerpreter sind einige ihrer Syntax-Eigenschaften schwer zu lernen.
# Dies betrifft vor allem LEERZEICHEN, die an manchen Stellen vorhanden sein
# MUeSSEN, an anderen Stellen aber NICHT erlaubt sind. Dies ist verwirrend, da
# in den ueblichen Programmiersprachen solche Regeln (meist) nicht existieren.
#-------------------------------------------------------------------------------
# TODO
# * Rechenoperationen nochmal ueberpruefen
# * Var. NICHT init. => Syntaxfehler oder Wert 0?
# DONE
# * Umlaute -> ae austauschen (portabel)
# * Regulaere Ausdruecke =~ !~ gibt es NICHT
# * @/set + Rechnen
#-------------------------------------------------------------------------------

#-------------------------------------------------------------------------------
# Variablen initialisieren (Leerzeichen um "=" notwendig!)
#-------------------------------------------------------------------------------
set  TXT  =                               # Leerer Wert
set  TXT  = ""                            # Leerer Wert
set  TXT  = ''                            # Leerer Wert
set TEXT  = EinWort                       # KEIN Quotierung  noetig
set TEXT2 = "Mehr als ein Wort"           # Quotierung  notwendig (Quotierung)!
set ZAHL  = 12345                         # Zahl (wird als Text repraesentiert!)

#-------------------------------------------------------------------------------
# Umgebungs-Variablen erzeugen und initialisieren
#-------------------------------------------------------------------------------
setenv GLOBAL "global"

#-------------------------------------------------------------------------------
# Shell/Umgebungs-Variable loeschen
#-------------------------------------------------------------------------------
unset TXT
unsetenv GLOBAL

#-------------------------------------------------------------------------------
# Signale abfangen (nur die Signale INT=Strg-C, HUP und TERM sind abfangbar!)
#-------------------------------------------------------------------------------
onintr INTMARKE                           # Bei Signal zu Label MARKE springen
onintr -                                  # Signale ignorieren
onintr                                    # Standardbehandlung der Signale

INTMARKE:
echo "Hier erfolgt die Signalbehandlung"

#-------------------------------------------------------------------------------
# Variable einlesen und ausgeben
#-------------------------------------------------------------------------------
echo -n "Eingabe: "                       # KEIN Zeilenvorschub nach "echo"
set INPUT = $<                            # Benutzereingabe (bis RETURN)
echo "Eingegeben wurde: $INPUT"

#-------------------------------------------------------------------------------
# Kommandosubstitution = Ausgabe eines externen Befehl in Shell weiterverwenden)
#-------------------------------------------------------------------------------
set LS_AUSGABE = `ls`                     # Dateiliste in Variable speichern
echo "LS_AUSGABE=$LS_AUSGABE"

#-------------------------------------------------------------------------------
# Bedingungen ueberpruefen ("test" liefert fuer "wahr/falsch" den Exit-Code "0/1",
#                         der in if, while und until zur Entscheidung dient)
# IMMER Gaensefuesschen bei Variablenzugriff (wg. leerer Var. => Syntaxfehler!)
# IMMER Leerzeichen um Operatoren (z.B. -r) und Operanden (z.B. /tmp) angeben
#-------------------------------------------------------------------------------
# (A) Zugriffsrechte testen
@ erg = ( -r /etc/passwd )                # Datei lesbar (r=readable)
@ erg = ( -w /tmp )                       # Datei schreibbar (w=writable)
@ erg = ( -x /usr/bin/bash )              # Datei ausfuehrbar (x=executable)

# (B) Datei-Existenz und -Groesse testen
@ erg = ( -e /usr/lib/include )           # Datei existiert (e=existent)
@ erg = ( -z /usr/bin )                   # Datei ist leer (z=zero)
@ erg = ( -s /usr/bin )                   # Datei ist NICHT leer (s=size)

# (C) Datei-Typen testen
@ erg = ( -f /etc/shadow )                # Name bezeichnet eine Datei (f=file)
@ erg = ( -d /usr/bin )                   # Name ... Verzeichnis (d=directory)
@ erg = ( -l /usr/bin )                   # Name ... Symbol. Link (l=symlink)

# (D) Strings vergleichen
@ erg = ( "$TEXT" == "ja" )               # Variable gleich Text
@ erg = ( "$TEXT" != "ja" )               # Variable ungleich Text
@ erg = ( "$TEXT" =~ "*ja*" )             # Variable passt zu Muster
@ erg = ( "$TEXT" !~ "*ja*" )             # Variable passt nicht zu Muster

# (E) Zahlen vergleichen
set ZAHL = 10                             # Var. NICHT init. => Syntaxfehler!
@ erg = ( "$ZAHL" == 10 )                 # Variable gleich 10 (eq=equal)
@ erg = ( "$ZAHL" != 10 )                 # Var. ungleich 10 (ne=not equal)
@ erg = ( "$ZAHL" <> 10 )                 # Var. ungleich 10 (ne=not equal)
@ erg = ( "$ZAHL" >  10 )                 # Var. groesser als 10 (gt=greater than)
@ erg = ( "$ZAHL" >= 10 )                 # groesser/gl. 10 (ge=greater or equal)
@ erg = ( "$ZAHL" <  10 )                 # Var. kleiner 10 (lt=less than)
@ erg = ( "$ZAHL" <= 10 )                 # kleiner/gleich 10 (le=less or equal)

#-------------------------------------------------------------------------------
# Rechnen (mit "expr" in jeder Shell einheitlich)
#-------------------------------------------------------------------------------
@ ZAHL = 0                                 # Klassisch per expr (Shell kann nicht)
@ ZAHL = `expr $ZAHL + 1 \* 9 % 5 - 4 / 2` # 0 + 9 % 5 - 2 -> 4 - 2 -> 2
echo "$ZAHL + 1 \* 9 % 5 - 4 / 2 -> $ZAHL" # Variable OHNE "$" NICHT erlaubt!

@ START = 111                              # Per "@"
@ ZAHL = $START + 111                      # KEINE Leerzeichen erlaubt!
echo "$START + 111 -> $ZAHL"               # Variable OHNE "$" NICHT erlaubt!

#-------------------------------------------------------------------------------
# Rechenoperatoren bei "@"
#-------------------------------------------------------------------------------
set ZAHL  = 123
set START = 456

@ ERG = $ZAHL + $START                     # + = Addition
echo "$ZAHL + $START -> $ERG"

@ ERG = $ZAHL - $START                     # - = Subtraktion
echo "$ZAHL - $START -> $ERG"

@ ERG = $ZAHL * $START                     # * = Multiplikation
echo "$ZAHL * $START -> $ERG"

@ ERG = $ZAHL / $START                     # / = Division
echo "$ZAHL / $START -> $ERG"

@ ERG = $ZAHL % $START                     # % = Modulo (Divisionsrest)
echo "$ZAHL % $START -> $ERG"

#@ ERG = $ZAHL \|\| $START                 # || = logisch OR
echo "$ZAHL || $START -> $ERG"

#@ ERG = $ZAHL && $START                   # && = logisch AND
echo "$ZAHL && $START -> $ERG"

@ ERG = ! $ZAHL                            # ! = logisch NOT
echo "! $ZAHL -> $ERG"

#@ ERG = $ZAHL | $START                   # | = bitweise OR
#echo "$ZAHL | $START -> $ERG"

#@ ERG = $ZAHL \& $START                   # & = bitweise AND
#echo "$ZAHL & $START -> $ERG"

@ ERG = $ZAHL ^ $START                     # ^ = bitweise XOR
echo "$ZAHL ^ $START -> $ERG"

@ ERG = ~ $ZAHL                            # ~ = bitweise NOT
echo "~ $ZAHL -> $ERG"

#@ ERG = $ZAHL << 2                      # << = bitweise left SHIFT
#echo "$ZAHL << 2 -> $ERG"

#@ ERG = $ZAHL >> 2                      # >> = bitweise right SHIFT
#echo "$ZAHL >> 2 -> $ERG"

#-------------------------------------------------------------------------------
# if-else if-else-Verzweigung
#-------------------------------------------------------------------------------
set ZAHL = 10                             # Leer. um "=" notwendig!
if ($ZAHL > 2) then                       # "then" muss hinter Klammer stehen,
	echo "if: $ZAHL ist groesser als 2"     # nicht auf einer neue Zeile!
else if ($ZAHL < 2) then                  # "then" nicht vergessen!
	echo "if: $ZAHL ist kleiner als 2"
else
	echo "if: $ZAHL ist gleich 2"
endif                                     # "endif" nicht vergessen!

#-------------------------------------------------------------------------------
# foreach-Schleife (Liste abarbeiten)
# (ACHTUNG: Hinter line-continuation "\" darf KEIN Zeichen mehr folgen)
#-------------------------------------------------------------------------------
foreach ELEM (abc defghi jklmnopqrstu vwxyz \
            vw xy z )                     # ELEM enthaelt Werte aus Wort-Liste
	echo "foreach-Durchlauf mit ELEM=$ELEM"
end                                       # "end" nicht vergessen!

#-------------------------------------------------------------------------------
# for-Schleife (die Shell-Argumente abarbeiten) GIBT ES NICHT!
#-------------------------------------------------------------------------------

#-------------------------------------------------------------------------------
# while-Schleife (Schleife wird durchlaufen, solange BEDINGUNG erfuellt ist)
#-------------------------------------------------------------------------------
set ZAEHLER = 5
while ($ZAEHLER > 0)
	echo "while-Durchlauf mit ZAEHLER=$ZAEHLER"
	@ ZAEHLER = $ZAEHLER - 1              # Leerzeichen NACH @ noetig!
end                                       # "end" nicht vergessen!

#-------------------------------------------------------------------------------
# until-Schleife GIBT ES NICHT!
#-------------------------------------------------------------------------------

#-------------------------------------------------------------------------------
# repeat-Schleife (feste Anzahl Wiederholungen)
#-------------------------------------------------------------------------------
repeat 5 echo "repeat-Schleife"

#-------------------------------------------------------------------------------
# Schleifendurchlauf oder gesamte Schleife vorzeitig abbrechen
# (mehrere Anweisungen mit ";" statt mit Newline zu trennen ist erlaubt!)
#-------------------------------------------------------------------------------
foreach I ( 1 2 3 4 5 6 7 8 9 10 )
	if ( "$I" == 3 ) continue            # Schleife bei "3" auf naechsten Wert
	if ( "$I" == 7 ) break               # Schleife bei "7" abbrechen
	echo "I=$I"
end

#-------------------------------------------------------------------------------
# Zaehlschleife (eher ungewoehnlich in der Shell)
#-------------------------------------------------------------------------------
foreach N ( 1 2 3 4 5 6 7 8 9 10 )
	echo "$N. Durchlauf"
end

foreach N ( `seq 10` )                   # Auch "seq 1 10" oder "seq 1 1 10"
	echo "$N. Durchlauf"
end

#-------------------------------------------------------------------------------
# Auswahl aus Liste GIBT ES NICHT!
#-------------------------------------------------------------------------------

#-------------------------------------------------------------------------------
# switch-case-Mehrfachverzweigung (Text-Vergleich mit Shell-Metazeichen)
# In Reihenfolge der Muster verglichen, Anweisungen nach 1. zutreffenden Muster
# werden ausgefuehrt, else-Zweig per "default" als letztem Fall realisieren.
#-------------------------------------------------------------------------------
set TEXT = "Moses"                        # Zum testen Zeilen vertauschen
set TEXT = "Mulut"                        # Zum testen Zeilen vertauschen
set TEXT = "Anton"                        # Zum testen Zeilen vertauschen
set TEXT = "Babel"                        # Zum testen Zeilen vertauschen
switch ( $TEXT )
	case A*:                              # MUSS auf Zeile fuer sich stehen!
		echo "case: Anton gefunden"
		breaksw                           # "breaksw" nicht vergessen!
	case M*:                              # MUSS auf Zeile fuer sich stehen!
		echo "case: Moses oder Mulut gefunden";
		breaksw                           # "breaksw" nicht vergessen!
	default:                              # MUSS auf Zeile fuer sich stehen!
		echo "case: Babel gefunden"
		breaksw                           # "breaksw" nicht vergessen!
endsw                                     # "endsw" nicht vergessen!

#-------------------------------------------------------------------------------
# Label und "goto" (besser nicht verwenden!)
#-------------------------------------------------------------------------------
echo "goto-Schleife, laeuft 3x durch"
set count = 3

MARKE:
if ($count == 0) goto ENDE                  # Schleife verlassen
@ count = $count - 1
echo "Hier bin ich"
sleep 1
goto MARKE

ENDE:

#-------------------------------------------------------------------------------
# Funktionen GIBT ES NICHT!
#-------------------------------------------------------------------------------

#-------------------------------------------------------------------------------
# Je nachdem, ob Skript-Parameter angegeben wurden oder nicht, etwas anderes tun
#-------------------------------------------------------------------------------
if ( $#argv >= 0 ) then
	echo "Folgende Skript-Parameter angegeben: $argv[*]"
endif
	echo "KEINE Skript-Parameter angegeben, setze selber welche!"
	set argv = ( Die im Skript gesetzten Parameter, falls keine von aussen gesetzt. )

#-------------------------------------------------------------------------------
# Skript-Aufruf-Parameter verarbeiten (SKRIPT PARAM1 PARAM2 ...)
#-------------------------------------------------------------------------------
echo "Skript-Name:                   $0"   # Im Skript verwendbar!
echo "Alle Skript-Parameter:         $argv[*]"
echo "Anzahl Skript-Parameter:       $#argv"
echo "1. Skript-Parameter (1. Wort): $argv[1]"
echo "2. Skript-Parameter (2. Wort): $argv[2]"
echo "3. Skript-Parameter (3. Wort): $argv[3]"
echo "4. Skript-Parameter (4. Wort): $argv[4]"
echo "5. Skript-Parameter (5. Wort): $argv[5]"
echo "6. Skript-Parameter (6. Wort): $argv[6]"
echo "7. Skript-Parameter (7. Wort): $argv[7]"
echo "8. Skript-Parameter (8. Wort): $argv[8]"
echo "9. Skript-Parameter (9. Wort): $argv[9]"

shift                                      # Kein Anzahl-Parameter erlaubt
shift
shift
echo "Alle Skript-Parameter nach shift 3: $argv[*]"

#-------------------------------------------------------------------------------
# Weitere spezielle Skript-Variablen
#-------------------------------------------------------------------------------
echo "Letzter Exit-Status:                      $?"   # <= Nur 1x lesbar, dann
echo "Letzter Exit-Status:                      $?"   # ist der Exit-Status
echo "Prozessnummer der Skript-Shell:           $$"   # des naechsten Kommandos
sleep 10 &                                            # darin zu finden.
echo "Nummer des letzten Hintergrund-Prozesses: $!"
### Eine Variable mit den gesetzten Shell-Optionen GIBT ES NICHT!

#-------------------------------------------------------------------------------
# Bedingte Variablen GIBT ES NICHT!
#-------------------------------------------------------------------------------

#-------------------------------------------------------------------------------
# Verzweigung abhaengig vom Skript-Namen
# (Kommandosubstitution per `...`)
#-------------------------------------------------------------------------------
set NAME = `basename $0 .sh`                   # Pfad und Endung ".sh" entfernen

if ( $0 == "tcshcode" ) then
	echo "Skript heisst 'tcshcode'"
else
	echo "Name des Skriptes lautet '$NAME'"
endif

echo "Pfad des Skriptes lautet `dirname $0`"   # Pfadanteil ausgeben

#-------------------------------------------------------------------------------
# Array-Variablen ausprobieren.
# * Eigentlich handelt es sich um "Wortlisten"
# * Indices sind numerisch von 1 bis 2041
# * Arrays sind 1-dimensional
# * Indices muessen nicht aufeinanderfolgen.
#-------------------------------------------------------------------------------
set arr = (1 22 33 4444 tom hans rick)
echo "arr=$arr"
echo "ANZ=$#arr"
echo "arr[1]=$arr[1]"
echo "arr[2]=$arr[2]"
echo "arr[3]=$arr[3]"
echo "arr[4]=$arr[4]"

set arr[2] = new
echo "arr=$arr"
echo "ANZ=$#arr"

#set arr[8] = 55555   # Geht nicht, da der Index schon existieren muss
#echo "arr=$arr"
#echo "ANZ=$#arr"

set arr = (1 2);       echo "arr($#arr)=$arr" # 2
set arr = ($arr $arr); echo "arr($#arr)=$arr" # 4
set arr = ($arr $arr); echo "arr($#arr)=$arr" # 8
set arr = ($arr $arr); echo "arr($#arr)=$arr" # 16
set arr = ($arr $arr); echo "arr($#arr)=$arr" # 32
set arr = ($arr $arr); echo "arr($#arr)=$arr" # 64
set arr = ($arr $arr); echo "arr($#arr)=$arr" # 128
set arr = ($arr $arr); echo "arr($#arr)=$arr" # 256
set arr = ($arr $arr); echo "arr($#arr)=$arr" # 512
set arr = ($arr $arr); echo "arr($#arr)=$arr" # 1024

@ ZAEHLER = $#arr
while ( 1 == 1 )
	@ ZAEHLER = $ZAEHLER + 1
	set arr = ($arr 9)
	echo "arr($#arr)=$arr"
	echo "$ZAEHLER"
end

#-------------------------------------------------------------------------------
# Assoziatives Array GIBT ES NICHT!
#-------------------------------------------------------------------------------

#-------------------------------------------------------------------------------
# Skript abbrechen mit Exit-Code 100
#-------------------------------------------------------------------------------
exit 100

