Shellscripts 101: Frage zu Syntax(?) bei Verwendung von Variablen und echo, evtl. weitere

Shellscripts 101: Frage zu Syntax(?) bei Verwendung von Variablen und echo, evtl. weitere

Hallo, dies ist mein erster Beitrag hier im Hackerboard.
Ich habe vor zwei Tagen angefangen, mir ein Skript zu schreiben und arbeite gerade ein bisschen Literatur dazu durch. Mir bleiben allerdings trotzdem noch Fragen unbeantwortet.

#!/bin/bash
function GetDaten()
{
# (Code, der vorname, nachname und email mit Werten füllt). Hier mal etwas Dummy-Code:
vorname=`./script2.sh parametera`
nachname=`script2.sh parameterb`
email="myemail@example.de"
}

a="noooo"
b="yeees"

for ((i=1;i<=5;i++))
do
GetDaten
echo "Vorname: ${vorname} Nachname: $nachname"
echo "Nachname: $nachname"
echo "Email: $email"
echo "a b argh!1 $a argh!2 $b argh!3"
done


Erzeugt folgende Ausgabe (eine Iteration):
Code:
 Nachname: myNachname
Nachname: myNachname
Email: myemail@example.de
a b argh!1 noooo argh!2 yeees argh!3

In der ersten Zeile fehlt etwas, oder? ("Vorname: " und der Wert von $vorname.) Wo ist der Unterschied zur testweise eingefügten letzten Zeile echo "$a argh $b"?
Interessant auch: Belege ich die Variable Vorname mit einem ausgeschriebenen String und nicht der Ausgabe eines anderen Skripts, so wird alles korrekt angezeigt.
Auch noch eine Frage: Wenn ich eine Variable mit einem Ausdruck in `solchen Akzenten` belege, wird die Anweisung dann bei der Belegun der Variable ausgeführt, oder, wenn ich die Variable verwende?

Soweit zu meinen ersten Fragen, sicher nicht die letzte.

Edit: Noch eine Frage: gibt es einen saubereren Weg, eine Zeichenkette in eine Datei zu schreiben? Ich mache es im Moment so:
Code:
echo "meine Zeichenkette abhängig von $variable" >> datei
Weiteres Problem: awk eine in meiner Shell bzw. im Skript bekannte Variable (einen Dateipfad) übergeben, der in der behandelten Datei gesucht werden soll.

PS: Lässt sich hier Code eingefärbter Syntax erzeugen? Die Formatierungsoptionen scheinen innerhalb der CODE-Tags ja leider nicht zu funktionieren. :(
 
Ich kann jetzt zwar auch net soo toll bash scripten, aber warum schreibst du
"${vorname}" und nicht "$vorname" ?

- MfG Keks :)

ps: nehm doch einfach den php-tag - besser als nix :)
 
Also bei mir funktioniert dein Script. Kopiers mal so hier aus dem Forum ;)
Wobei es darauf ankommt, was als Vor- und Nachname zurückgegeben wird. Bei dir siehts danach aus, als ob es beim Vornamen am Ende ein "\r" hat.

Wenn du in einer Variable die Ausgabe eines Befehls haben möchtest (ausgeführt bei der Zuweisung, nicht bei jeder Benutzung), wird die neue Variante empfohlen:
Code:
deinevariable=$(deinkommando mit parametern)

Die Klammern werden um den Variablennamen eigentlich nur gesetzt, wenn kein Trennzeichen darauf folgt:
Code:
test="bla"
echo "${test}bla"

Um Text an eine Datei anzuhängen ist dein Weg der normale im Bash-Skript ;)

Du kannst in awk die normalen Bash-Variablen benutzen, du musst nur darauf achten, dass du alles richtig escapest :D
 
Danke schon an keksinat0r und lagalopex. PHP-Tags passen leider nicht so richtig zur Syntax hier. :/

Code:
foo=$(kommando parameter)hierstehteinstring$(nocheinkommando nochmehrparameter)
funktioniert leider nicht (Fehler "bad substituition"). Geschweifte Klammern außen und innen habe ich auch erfolglos versucht.

Außerdem habe ich versucht, eine Variable, die so belegt wurde als Zahl zu behandeln - das klappt auch nocht nicht so ganz...
Ans Escapen habe ich bei Umgebungs-Variablen noch nicht gedacht. So sollte es dann aber vielleicht klappen, den dem Skript, in dem ich awk aufrufe, übegebenen Parameter zu benutzen:
(Format einer Zeile in der mit awk behandelten Datei "db": Zahl Dateiname)
Code:
var=$(awk '/\$1/ {print $1}' db)
um die zur gesuchten Datei passende Zahl auszugeben. (Hoffentlich kann ich dies dann auch als Zahl weiterverwenden - damit habe ich mich gerade auch ziemlich lang herumgeschlagen...


Hier nochmal genau, wo ich eine fehlerhafte Ausgabe beim echo hatte. Ich habe dieses Skript benutzt.

Code:
#!/bin/bash
vorname=$( ./randomline.sh ./namen/vornamen)
nachname=$( ./randomline.sh ./namen/nachnamen)
echo "Vorname: ${vorname} Nachname: $nachname"
erzeugt das oben gesehen Phänomen, um genau zu sein (sowohl bei Einschluss der Aufrufe mit $( ), als auch mit ` `.


Den Spaß oben habe ich übrigens gemacht, weil ich vermute, dass der Aufruf von wc -l in diesem Skript randomline bei einer Datei mit ein paar zehntausend Zeilen recht teuer ist, im Vergleich dazu, sich eine Zeile herauszupicken. Liege ich damit überhaupt richtig? Vielleicht kommt das lange Warten daher, dass der Zufallspool für den Aufruf von $RANDOM auf neues Rauschen warten muss...

Noch mehr aussagekräftige Fehler...
: command not found5:
: command not found2:
: command not found0: und nach dem Entfernen von ein paar zusätzlich eingefügten Debug-Statements:
: command not found9:
In dieser Reihenfolge, jeweils nach dem Entfernen eininiger Zeilen, und immer als allerletzte Zeile der Ausgabe... ich habe jetzt bestimmt insgesamt auch schon einmal das komplette Programm auskommentiert - das kommt wohl davon, viel auf einmal zu ändern...
 
Code:
foo=$(echo eins)zwei$(echo drei)
Funktioniert einwandfrei. Wobei ich hier lieber Anführungszeichen setze.
Code:
foo="$(echo eins)zwei$(echo drei)"

Wenn da in der Datei nen Zahl und nen Dateiname steht, nimm doch einfach:
Code:
foo=$(sed -n "s#^\([0-9]*\) $1\$#\\1#p" db)

Und du kannst Variablen immer als Zahlen benutzen, wenn sie Zahlen enthalten, da es sowas wie Typen (int, string, ...) nicht gibt.

Sonst zeig mal alle Scripts, so dass wir den Fehler reproduzieren können. ;)
 
Wenn da in der Datei nen Zahl und nen Dateiname steht, nimm doch einfach:
Code:
foo=$(sed -n "s#^\([0-9]*\) $1\$#\\1#p" db)

Mal sehen, ob ich als ziemlicher Anfänger da durchsteige... sed, Streameditor, von dem ich schon mal am Rande gehört hab.
-n automatische Ausgabe unterdrücken, okay.
s - das mächtige Kommando zum Ersetzen.
Jetzt kommt eine Raute... ist das ein Ersatz für s/regexp/replacement/, wie es in der manpage steht?
also... die Zeile ersetzt Ausdrücke, die eine beliebig lange (*) Zahl ([0-9]) am Anfang (^) stehen haben (die Klammern mit \ davor werden im Sinne von regulären Ausdrücken interpretiert und nicht als Klartext, nehme ich an?) mit "\\1"...ist das das erste Argument/Wort in der Zeile?
p - Print the current pattern space.

Die Meldungen ^ : command not found[0-9]: $ ließen sich dadurch lösen, dass ich Leerzeilen am Ende des Skripts entfernt habe... so erstmal weitermachen. Code kommt hoffentlich auch noch. :D


Erkenntnisse wäre noch hinzuzufügen: Ich habe festgestellt, wie ich arithmetische Ausdrücke berechnen kann - die Shell mag sowas wie "var= $var +2" nicht... So kann ich auch endlich größere Zufallszahlen erzeugen:
zufallszahl=$((($RANDOM * 32768 + $RANDOM) % $RANGE + $MIN ))
Allerdings sind die Zufallszahlen dann nicht gleichverteilt...
gibt es noch eine intuitive Möglichkeit, wie ich beispielsweise Zahlen zwischen 0 und 999 mit theoretisch exakt gleicher Wahrscheinlichkeit erzeuge?
wenn ich einfach sage zahl=$(($RANDOM % 1000)) sind ja 0-767 wahrscheinlicher als größere Zahlen. Das mag in diesem Fall vielleicht nicht so extrem sein, wenn ich aber % 32767 rechne, ist die 0 doppelt so wahrscheinlich wie jede andere Zahl!
Außer mit anderen Zweierpotenzen als Obergrenze sehe ich keine Möglichkeit, das zu umgehen :-S

Das ist in der Praxis vielleicht unerheblich, ich mache mir darüber aber Gedanken. Beim elektronischen Glücksspiel könnte man sich so etwas jedenfalls nicht leisten, das würde teuer.

Hier mal noch meine Funktion, die ich gerade gebastelt habe (beleadene Syntax mit diesen vielen Klammern...aber immerhin funktioniert's :)
Code:
function rand #Parameter: $1: minimaler Wert. $2: Größe des Bereichs, aus dem die Zahlen kommen können
{
echo "$((($RANDOM * 32768 + $RANDOM) % $2 + $1))"
}
 
Die Klammer im sed ausdruck umschließt den Teil, der später als \1 referenziert wird. ;)

Die Ungleichverteilung lässt sich recht leicht korrigieren.
Die Zufallszahlen sind ja gleichverteilt, wenn die maximale zufallszahl ein vielfaches des bereichs ist. Also muss einfach geschaut werden, was die maximale zufallszahl sein dürfte, damit das zutrifft und verwirft einfach zufallszahlen, die über dieser grenze liegen.

PHP:
function rand # min max
{
	d=$(($2-$1+1))
	up=$((1073741823/$d*$d))
	while true
	do
		r=$(($RANDOM*32768+$RANDOM))
		if test $r -le $up
		then
			echo $(($r%$d+$1))
			break
		fi
	done
}
 
Zurück
Oben