Dollarzeichen ($) vor Variablen in Shellskripts

Bruce_L

Cadet 4th Year
Registriert
Okt. 2010
Beiträge
67
Hallo,

bei Shellskripts wird ja bei der Definition von Variablen dem Variablennamen kein Dollarzeichen vorangesetzt, nur beim Zugriff auf Variablen kommt ein '$' davor. Bei PHP z. B. setzt man dagegen immer ein Dollarzeichen voran.

Jetzt frage ich mich natürlich als Linux-Noob: Gibt es da einen tieferen Sinn, warum das so ist? Eigentlich finde ich die PHP-Konvention viel logischer...

Für so etwas kann man es ja z. B. nicht benutzen:
Code:
a=b
$a=x
echo $b
das gibt mir nicht 'x" aus, sondern
Code:
bash: b=x: command not found
 
Mit dem Dollarzeichen gibtst du der Shell eine Substitution an.
"$a" sagt der Shell, sie soll an dieser stelle nicht die Zeichenkette "a" verwenden, sondern den Variableninhalt von "a".
Links einer Zuweisung wird ein Variablenname erwartet und nicht der Inhalt einer Variable, von daher hier kein "$"
 
Kann es auch nicht, denn du weisst b an a zu und dann das x an a und lässt b ausgeben was nicht existiert; Was geht ist das


Code:
a=x
b=$a
echo $b
 
Zuletzt bearbeitet:
Danke für die Antworten, aber nochmal zur eigentlichen Frage: Gibt es einen tieferen Grund, warum die Konvention gerade so ist und nicht wie bei PHP?
 
ich könnte mir vorstellen dass die shell hier zwischen speicheradresse und inhalt an dieser adresse unterscheidet, weeß et aba nick.

dein beispiel wäre dann also:

erstelle objekt und speichere adresse in a.
speichere adresse von objekt b in a.
weise dem INHALT der adresse die in a gespeichert ist den string "x" zu (bei dir fehlen die anführungsstriche, das kann so nicht gehen^^ das wird sonst von der shell als gesuchtes binary interpretiert, das ist aper nicht in $PATH und somit 'not found').
gebe den INHALT der adresse die in b gespeichert ist aus.

bei PHP muss man sich darüber offensichtlich keine gedanken machen. bei shellscripts in der regel auch nicht, man macht es halt beim ersten erscheinen ohne $, dann passt das meistens.
 
hätte auch in die richtung refernzen und objekt dereferzierung gedacht;
 
ja es gibt einen sinn.. das was php macht ist eigentlich das was von beiden lösungen weniger sinn macht. der grund ist ganz einfach.. $ ist bei bash ein operator, bei php ist es teil des variablennamens. $xxx ist eine substitution, d.h. bash ersetzt es mit dem wert der variablen xxx.

folgendes bezieht sich auf bash:
x=123 # wert der variable x auf "123" setzen
y=$x # wert der variable y auf "$x" = "123" setzen
echo x # gibt das zeichen x aus
echo $x # gibt den wert der variablen x aus -> "123"
Ergänzung ()

M0rpHeU5 schrieb:
hätte auch in die richtung refernzen und objekt dereferzierung gedacht;

bash kennt keine objekte und auch keine referenzen im eigentlichen sinne.
 
Es ging ihm um die linke Seite der Zuweisung. Da scheitert die simple Erklärung mit der Substitution jedes $dingsbums recht schnell. Da

a=5

funktioniert, sollte bei simpler Substitution aller $dingsbums folgendes die gleiche Zuweisung machen:

b=a
$b=5

Tuts aber nicht. Ganz so einfach ist es also nicht.
 
ganz so exakt habe ich es auch nicht gemeint, nur das man es sich ungefähr vorstellen kann; ja war schlecht gewähltes bsp;
 
wieso sollte bei substitution denn bitte
b=a
$b=5
funktionieren? gerade bei substitution kann es nicht funktionieren..

$b wird _vor_ der verarbeitung der zeile $b=5 ersetzt.. dann steht dort "a"=5 ..
 
IceMatrix schrieb:
$b wird _vor_ der verarbeitung der zeile $b=5 ersetzt.. dann steht dort "a"=5 ..
Ohne "". Dort steht dann a=5. Und dieses aus $b=5 dank Substitution entstandene a=5 verhält sich anders als ein direkt an die gleiche Stelle hingeschriebenes a=5. Das erste wird ein Programm namens a=5 starten wollen, das zweite ist eine funktionierende Zuweisung.

Das Bsp. zeigt, dass "einfach alle $... substituieren und dann weiter wie gehabt" eben nicht funktioniert - jedenfalls nicht auf der linken Seite einer Zuweisung, um die es in dem Thread hier geht. Die linke Seite der Zuweisung ist in sh schlichtweg anders definiert als in PHP.
 
es ist aber nicht ohne ""... $a ist eine zeichenkette. für alles andere kann man eval verwenden, z.b. eval "$a=5"
 
Zuletzt bearbeitet:
ich denke, man kann es so formulieren:

Ein Array aus Strings (ohne reservierte Wörter) wird von der bash immer als Kommando, das ausgeführt werden soll, angesehen. Die einzelnen Elemente des Felds sind durch Leerzeichen getrennt. So etwas geht ja z. B.:
Code:
"ls" "-l"
während so etwas nicht geht:
Code:
"ls -l"

In so einem Fall, also wenn es um Kommandos geht, klappt eine Substitution:
Code:
a=ls
b=-l
$a $b
Wenn es sich aber um von der "Sprache" bash reservierte Wörter oder Konstrukte handelt, die intern – wie meine Vorposter schon angesprochen hat – nicht als Strings behandelt werden, funktioniert das ganze nicht.

So etwas einfaches klappt schon nicht mehr (es lässt sich zwar ausführen, gibt aber nicht das aus, was man erwartet):
Code:
#!/bin/bash
N=10
for i in {1..$N}
do
  echo "Hallo $i-mal!"
done
es führt kein Weg an dieser Lösung vorbei:
Code:
#!/bin/bash
for i in {1..10}
do
  echo "Hallo $i-mal!"
done
Ich muss sagen, ich bin fast schon etwas geschockt, ;) wenn man sich anschaut, wie extrem beschränkt die Programmiersprache bash ist, fragt man sich, ob es sich überhaupt lohnt, sich tiefer damit zu beschäftigen... das ist natürlich nur meine laienhafte, erste Einschätzung... :cool_alt:
 
Zuletzt bearbeitet:
es lohnt sich! wenn man bash-skripte schreiben möchte :lol:

für alles andere gibt es je nach zweck besseres. perl, php, python, [lieblingsprogrammierspracheeinsetzen], sogar javascript.

ich benutze shellskripte um vorhandene programme sinnvoll zu verknüpfen, z.b. ein backup mit rsync zu realisieren, das enthält nur sehr simple konsistenzchecks, die eigentliche logik steckt in rsync, mount etc.
um jedoch rsync selbst zu schreiben wäre ein shellskript eine tortur.
 
Der Grund, dass man es so schreiben muss:

a=5;
echo $a;

liegt daran, dass man mit a=5 eine umgebungsvariable setzt.
mit $ ruft man diese Variable auf. In der Bash arbeitet man nur mit Umgebungsvariablen.
Die bekannteste ist PATH. Diese kannst du mit echo $PATH anschauen.

Und Bash ist auch keine Programmiersprache. Es ist eine Shell.
Jeder Befehl, den man in der Bash aufrufen kann, ist nichts weiter als ein anderes Programm. z.B. echo: Echo ist ein Programm, was vom stdin liest/die Parameter nimmt und sie auf stdout ausgibt.

Auf diese Weise lässt sich die Bash nach belieben erweitern. Wenn man meint, man hat ein tolles Kommandozeilenprogramm entwickelt, kann er dies für seine Bash-Skripte benutzen.

Das Zeichen [ ist lediglich ein Alias für das Programm Test.
Also if [-f "$file"] lässt sich auch mit if test -f "$file" beschreiben.

Ich bin jetzt zwar ein bisschen raus aus der Shell-Entwicklung, aber müsste das nicht funktionieren:
Code:
#!/bin/bash
N=10
for i in {1..`echo $N`}
do
  echo "Hallo $i-mal!"
done

echo $N wird als Befehl ausgeführt und es steht dann dort 10 und {1..10} ist wiederrum eine reguläre Menge.
 
Ne, funktioniert nicht (zumindest bei mir auf Cygwin).
 
Hallo {1..10}-mal!
:lol:

wird offensichtlich von bash trotz sub-shell nicht als operator verstanden.
vielleicht weil echo ein \n anhängt? grad kein bock das rauszupipen, aber wäre eine idee wert.
 
mmmh...
Die Ausgabe davon
Code:
gruss=`echo Hallo`
echo "$gruss $gruss"
spricht dagegen, dass echo ein \n anhängt, es gibt keinen Zeilenumbruch zwischen den beiden "Hallo".
 
dazwischen doch nicht, am ende! oder erscheint das shell-prompt unmittelbar nach der ausgabe von echo? wenn ich das \n kille ja (zugegeben das war stdout). die subshell zwackt es vielleicht wieder ab?
 
Zuletzt bearbeitet von einem Moderator:
Zurück
Oben