• Willkommen im Linux Club - dem deutschsprachigen Supportforum für GNU/Linux. Registriere dich kostenlos, um alle Inhalte zu sehen und Fragen zu stellen.

[gelöst] if [ ${0##*/} = "sim_tree" ]

infocheck

Newbie
Hallo !

Was bedeutet dieser Ausdruck
if [ ${0##*/} = "sim_todo" ];

Er prüft in einem Skript den Namen des aufrufenden Skripts.
Dies liegt in unterschiedlichen Namen vor, wie:

- sim_todo
- sim_todo_simple
- sim_todo_ext

Danke für Antworten.
 

leanUX

Member
$0 bzw ${0} ist der Name des aufgerufenen scripts.

Das Ergebnis des Audrucks ${0##*/} ist der ursprüngliche Inhalt von $0,
reduziert um den längsten Match von */ (also beliebige Zeichenfolge die mit einem / endet)
vom Anfang her.

Beispiel:
Sagen wir $0 sei foobar/dingens/whatever , dann ist der längste match von */ vom Anfang her foobar/dingens/
um den wird $0 ja reduziert,
d.h. das Ergebnis wäre dann whatever
 
A

Anonymous

Gast
infocheck schrieb:
Was bedeutet dieser Ausdruck
if [ ${0##*/} = "sim_todo" ];

(War schon jemand schneller, aber jetzt habe ich meine Antwort auch fertig, also poste ich meinen Senf auch noch dazu, obwohl die Lösung oben schon steht.)

Nichts einfach als das. muss man nur auseinander nehmen.
Code:
if [ ................... ];
es wird also irgend was getestet und anschließen mit then... else ...fi darauf reagiert.
Der Kackpunkt des Verstehens ist also nur
Code:
${0##*/}
das wird gegen den String "sim_todo" auf Übereinstimmung getestet, das kann man ja noch ganz leicht erkennen.

$0 das ist der Name des aufgerufene Befehls, bzw der aufgerufene Script- oder Funktionsname.
Ein Script kann man nun aber verschieden aufrufen.
Code:
script.sh
./script.sh
/root/bin/script.sh
../bin/script.sh
~root/bin/script.sh
und noch in tausend anderen Variationen. Wenn man jetzt den Scriptnamen zu einem Vergleich benötigt, muss man alles vor, und einschließlich des letzten "/" wegschneiden ehe man vergleichen könnte.
OTTO-Normal-User wird hier meist sein Glück mit sed probieren. Im einfachsten Fall dann so.
Code:
echo $0 | sed 's/.*\///'
das eingebaut in den Test von oben sieht dann wie folgt aus.
Code:
if [ $(echo $0 | sed 's/.*\///') = "sim_todo" ];
Und das funktioniert ist aber nicht schön, da hier einerseits erst ein Bashbuiltin (echo) und noch ein extra Befehl (sed) aufgerufen wird, die beide über eine auch noch zusätzlichen Pipe arbeiten, und das ganze noch in eine Kommandosubstitution verbaut werden muss. Das muss auch einfacher gehen und geht es natürlich auch. Man könnte zB den Befehl "basename" verwenden, bleibt aber immer noch auf einem zusätzlichen Befehlsaufruf und der Kommandosubstitution sitzen, versuchen wir es doch einfach mal mit der bash selbst, die kann auch eine ganze Menge und an solche Standardsachen hat man dort sicherlich auch gedacht.

Also nimmt man sich die Manpage der bash und sucht sich mal die Stringmanipulatoren, also mal bis zum Abschnitt "Parameter Expansion" springen.
dort sollte zu finden sein.
${parameter##word}
Remove matching prefix pattern........the longest matching pattern (the ``##'' case) deleted.
Also Parameter ist die Variable und ist "$0" und Pattern wäre das was wir suchen also "/" , probieren wir mal gleich innerhalb unserer Shell aus, "echo $0" gibt "/bin/bash" wir suchen nur "bash".
Code:
echo ${0##/}
und erhalten "bin/bash"
funktioniert schon ein bisschen aber noch nicht ganz. es wird immer nur ein eventuelles erstes "/" entfernt. Also wir müssen jetzt noch Pattern etwas anpassen, damit nicht nur ein einzelnes Zeichen sondern ein Bereich gesucht wird und somit den ganzen eventuellen Path vor dem Befehlsnamen abgeschnitten wird.
suchen wir weiter in der Manpage von bash nach "Pattern Expansion" und setzten dann noch ein "*" vor das "/" und meinen damit "Alles vor und einschließlich /"
Code:
echo ${0##*/}
zeigt jetzt auf der Konsole "bash" das sollte auch so bleiben, egal wie die Bash aufgerufen würde und würde bei jedem Script genauso funktionieren, also jetzt können wir diesen Ausdruck übernehmen und kommen auf die Ausgangszeile von oben


Nun könnte man sich fragen, " für was kann man sowas gebrauchen?"

ZB. man hat "irgendwas" das muss gestartet und gestoppt werden mittels Script. Dazu sind eine ganze Menge Programmiertext notwendig. Schreibt man das in 2 Scripte, dann hat man viele Unterfunktionen und Konfigurationen und Einstellungen in beiden Scripten die eigentlich gleich sind. 2. Scripte, der Aufruf währe dann
Code:
startscript
stopscript
Das ist naturlich schlecht zu warten.
Man könnte es auch in ein Script schreiben und das Script dann mit einer zusätzlichen Option beim Aufruf zum steuern versehen also zB der Aufruf dann
Code:
script.sh start
script.sh stop

oder man schreibt es in ein Script und verzweigt mit dem obrigen Test entsprechend dem aufgerufenen Scriptnamen dieser könnte dann einfach"start" und "stop" sein.
Jetzt legt man das Script als Datei "start" ab und legt einen Hardlink auf "stop". Der Aufruf jetzt
Code:
start
stop
der ganze Code ist in einer einzigen Datei und leicht zu warten, man hat aber scheinbar 2 Scripte, die ganz einfach in der Anwendung sind.

robi
 
OP
I

infocheck

Newbie
leanUX schrieb:
$0 bzw ${0} ist der Name des aufgerufenen scripts.

Das Ergebnis des Audrucks ${0##*/} ist der ursprüngliche Inhalt von $0,
reduziert um den längsten Match von */ (also beliebige Zeichenfolge die mit einem / endet)
vom Anfang her.

Beispiel:
Sagen wir $0 sei foobar/dingens/whatever , dann ist der längste match von */ vom Anfang her foobar/dingens/
um den wird $0 ja reduziert,
d.h. das Ergebnis wäre dann whatever


Super. Danke für die Erklärung.
Nun ist der vorliegende Skriptcode nachvollziehbar.
 
OP
I

infocheck

Newbie
robi schrieb:

Das sind ja eine ganze Menge Zusatzhinweise
rund um solche Einsatzmöglichkeiten.

Das erleichert nun den Umgang mit Substitutionen
bzw. alternativen Möglichkeiten.

Da Linux für mich recht neu ist, war das sehr hilfreich.
 

abgdf

Guru
infocheck schrieb:
abgdf schrieb:
Keine Ahnung, wozu Du das wissen willst.
Ganz einfach.
Ich darf mich in einen Code von einem Vorgänger einarbeiten.
Versöhnt Dich das ?
Ja. :p

Die Sache war ja, daß da offenbar $0 untersucht wurde. Insofern dachte ich, "muß er den Rest des Ausdrucks jetzt auch unbedingt noch verstehen"? Dafür fehlte mir irgendwie der Grund. Ohne solchen triftigen Grund hätte ich wahrscheinlich den Code zu etwas geändert, das ich verstanden hätte, z.B.
Code:
if test "$0" = "sim_tree"; then ...
bzw., wenn untersucht werden soll, ob der Dateiname mit "sim_tree" beginnt, was mit
Code:
echo "$0" | grep "^sim_tree"
Am Ende kommt man dann aber doch zu dem, was robi ausführlich erklärt hat (da man meistens wohl doch den Pfad wegschneiden muß). :)
 
Oben