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

Kurze Erläuterung eines Perlskriptes

Liebe Linuxfreunde,

mir ist aufgefallen, dass viele Perl-Skripte eine im Kopf folgende Zeilen enthalten:

Code:
#!/bin/sh
#! -*- perl -*-
eval 'exec $PERLLOCATION/bin/perl -x $0 ${1+"$@"} ;'
 if 0;

Ich verstehe leider nicht so recht, was das soll. Ich weiß zwar, dass -x überprüft, ob eine Datei ausführbar ist oder nicht. Desweitern beinhaltet $0 den Namen des Sriptes. Was macht aber der Rest!?

Danke für eure Hilfe.
earlgrey_tea

Ps.: $@ lässt sich nicht bei goole suchen :/
 
A

Anonymous

Gast
das ist eine kleine Wissenschaft für sich.

Code:
eval 'exec $PERLLOCATION/bin/perl -x $0 ${1+"$@"} ;'

es geht hier darum Perl mit der Option -x zu starten und die Argumente des Scripts an Perl zu übergeben.

Die Bedeutung der einzelnen Variablen kann man zB in der Manpage der Bash unter "Special Parameters" nachlesen
$0 ist zum Beipiel der Name des Scriptes selber.
$1 das erste Argument mit dem das Script aufgerufen wurde.
$* und $@ sind zB alle übergebenen Argumente ( $1 $2 $3 ......)
"$@" ist schon wieder ein Spezialfall "$1" "$2" "$3" .......

Das was dort mit dem ganzen Konstrukt gemacht wird ist dann ein kleiner Trick mit man sicherstellt, dass der ganze Funktionsaufruf sowohl unter verschiedenen Shells als auch unter Perl funktioniert und hier auch Argumente mit Leerzeichen oÄ sauber an Perl als Argumente übergeben werden. In der Gesamtheit ist das recht komplziert wenn man es genauer auseinanderlegt, da hier auch noch mehrere weitere Befehle oder Builtins vorgeschalten sind und so die Interpretation durch die Shell mehrfach erfolgt und dadurch auch noch durch ' geschützt werden muss.

Optionen. (dort nach "-S" suchen), da ist das ein bischen beschrieben. Muss man alles nicht wissen und schon gar nicht verstehen, das übergibt einfach ausgedrückt die Argumente mit dem das Script aufgerufen wird, an Perl . ;)

robi
 
robi schrieb:
Die Bedeutung der einzelnen Variablen kann man zB in der Manpage der Bash unter "Special Parameters" nachlesen
Die Manpage der bash :irre: Da wär ich ohne Hinweis nicht so drauf gekommen.

robi schrieb:
In der Gesamtheit ist das recht komplziert wenn man es genauer auseinanderlegt, da hier auch noch mehrere weitere Befehle oder Builtins vorgeschalten sind und so die Interpretation durch die Shell mehrfach erfolgt und dadurch auch noch durch ' geschützt werden muss.

Kannst du mir eine Internetseite/ Buch (auch in Englisch) empfehlen, wo das Ganze auseinandergelegt wird (ähnlich wie die von dir angegebene http://www.cs.cmu.edu/afs/cs.cmu.edu/Web/People/rgs/pl-opt.html)? Ich kenne zwar einige grundlegende Einführungen in Pearl, die beschränken sich aber auf die Grundlagen und helfen einem bei Fragen - ähnlich meiner - wenig bis gar nicht weiter.

Ich weiß, dass man das nicht unbedingt verstehen muss, aber ICH WILL :D Ich krich 'nen Rappel, wen ich Skripte ausführe, die ich nicht verstehe.

Kann es sein, dass du dich bei:
robi schrieb:
"$@" ist schon wieder ein Spezialfall "$1" "$2" "$3" .......
geirrt hast?

Ich hab auf der Seite http://www.cs.cmu.edu/afs/cs.cmu.edu/Web/People/rgs/pl-predef.html#$@ Folgende Info gefunden:
Code:
$@ The perl syntax error message from the last eval  command. If null, the last eval  parsed and executed correctly (although the operations you invoked may have failed in the normal fashion). (Mnemonic: Where was the syntax error "at"?)

Würde ja auch besser zum Ansatz des Skriptkopfes passen, der meiner Meinung nach mindestens zweimal aufgerufen wird. Bei einem mehrmaligen Aufruf würde "$@ = The perl error message from last eval (...)" auf jeden Fall Sinn machen.
Was aber für deine Interpretation auch gilt (ebenfalls sinnvoll). :???:
Was meinst du?

Vielen Dank
earlgrey_tea
 
A

Anonymous

Gast
earlgrey_tea schrieb:
Kannst du mir eine Internetseite/ Buch (auch in Englisch) empfehlen, wo das Ganze auseinandergelegt wird (ähnlich wie die von dir angegebene http://www.cs.cmu.edu/afs/cs.cmu.edu/Web/People/rgs/pl-opt.html)? Ich kenne zwar einige grundlegende Einführungen in Pearl, die beschränken sich aber auf die Grundlagen und helfen einem bei Fragen - ähnlich meiner - wenig bis gar nicht weiter.

ich stehe mit Perl etwas auf Kriegsfuss, bzw ich hab es noch nicht geschaft mich wirklich umfassend und ausführlich damit zu befassen, da ich wohl sonst noch genügend andere Sprachen und Scriptsprachen kenne und nicht so wirklich darauf angewiesen bin. Ich muss sowas nur ausführen können und eventuell ein paar Kleinigkeiten ändern.

Wenn ich da was spezielles suche, ich finde im Web eigentlich immer was passendes. grade Perl ist ja das Web voll. Der Link oben stammt zB aus http://www-cgi.cs.cmu.edu/cgi-bin/perl-man
ist zwar Perl 4 aber was soll's ich kenne sowieso den Unterschied nicht. Hier tummeln sich allerdings einige Stamm-User regelmäßig rum, die mit Perl mehr am Hut haben. zB framp oder abgdf oder andere die mir grade nicht einfallen. Die haben sicherlich ein paar heiße Links für dich.

robi
 
Wenn ich das Kamel-Buch da richtig verstehe, ist $@ letztlich so etwas wie $! nur das es garantiert gesetzt wird. $! wird bei einem Fehler auf wahr gesetzt aber beim nächsten eval der ohne Fehler durchlief nicht auf falsch gesetzt. $@ wird bei einem fehlerfreien Lauf auf falsch gesetzt. Der nächste Unterschied scheint darin zu bestehen das $@ auch ein Ausnahmeobjekt sein kein, also nicht zwingend ein String sein muß. Aber das ist jetzt nur ohne wirklich tieferes Verständnis aus dem Buch gelesen.
 
Geier0815 schrieb:
Wenn ich das Kamel-Buch da richtig verstehe

Ich hab mir das Kamel grad bestellt; Montag kann ich hoffentlich etwas kompetenter mitreden :D

Geier0815 schrieb:
$@ wird bei einem fehlerfreien Lauf auf falsch gesetzt. Der nächste Unterschied scheint darin zu bestehen das $@ auch ein Ausnahmeobjekt sein kein, also nicht zwingend ein String sein muß.

Aber müsste da nicht eigentlich ein numerischer Wert 'rauskommen? Wegen:
Code:
${1+"$@"} ;'
if 0;

"${1+"$@"}" sieht doch stark nach einer Zahl als Ergebnis aus...

Viele Grüße
earlgrey_tea
 
Hallo,
Code:
#!/bin/sh
#! -*- perl -*-
eval 'exec /usr/bin/perl -x $0 ${1+"$@"} ;'
if 0;
Denke, es wir so sein:

1. sh startet,
2. Zeile 2 wird ignoriert (#).
3. eval wertet den String in '' aus,
4. exec ersetzt die Shell sh durch /usr/bin/perl,
5. perl wird mit -x gestartet und der Argumentenliste:
$0 ist der Skriptname, ${1+"$@} sind die weiteren Argumente, beides in sh-Syntax.
Beweis:
Code:
#!/bin/sh
echo ${1+"$@"};
echo $@;
# Bitte mit ein paar Argumenten starten.
6. perl -x interpretiert alles, was nach einer Zeile mit "#!" am Anfang und mit "perl" drin kommt, als Perl-Code, siehe "perldoc perlrun".
7. Zeile 3 wird nochmal interpretiert, diesmal aber als Perl-Code, das heißt eval und exec würden nochmal gestartet, diesmal aber als Perl-Befehle, siehe "perldoc -f eval" und "perldoc -f exec",
8. dies wird unterbunden durch "if 0;", im Ganzen würde das eigentlich heißen
Code:
if (0) {eval '...';}
9. Da "if (0) {...}" nie ausgeführt wird, werden Punkte 7. und 8. unterbunden,
10. Das Skript läuft als Perl-Skript weiter hinter "if 0;".

Gruß
 
abgdf schrieb:
8. dies wird unterbunden durch "if 0;", im Ganzen würde das eigentlich heißen
Code:
if (0) {eval '...';}
Aber das if 0 steht doch hinter der exec Anweisung, wie kann es die dann abbrechen?:
Code:
eval 'exec /usr/bin/perl -x $0 ${1+"$@"} ;'
if 0;

Ansonsten, danke für die super Erklärung!

Viele Grüße
earlgrey_tea
 
earlgrey_tea schrieb:
abgdf schrieb:
8. dies wird unterbunden durch "if 0;", im Ganzen würde das eigentlich heißen
Code:
if (0) {eval '...';}
Aber das if 0 steht doch hinter der exec Anweisung, wie kann es die dann abbrechen?:
Code:
eval 'exec /usr/bin/perl -x $0 ${1+"$@"} ;'
if 0;
Das ist eine der vielen Syntax-Verkürzungen, die Perl zuläßt. Es ist so gemeint:
Code:
#!/usr/bin/perl -w
use strict;
print "Hallo\n" if 0;
# ist dasselbe wie:
if (0) { print "Hallo\n"; }
Der Zeilenumbruch zwischen eval ... und if ... wird als Perl-Code als Whitespace ignoriert.
Ansonsten, danke für die super Erklärung!
Gern, war tatsächlich ganz schöne Knobelei ...

Viele Grüße
 

framp

Moderator
Teammitglied
Es ist wohl alles soweit ausführlich erklärt worden. Weitere Details dazu sind auch hier (in English) nachzulesen. Im Wesentlichen geht es in dem Konstrukt darum perl Scripts auch unter shells, die kein #! kennen, dazu zu bringen, erfolgreich zu starten. Ist allerdings mittlerweile ziemlich unüblich und veraltet.
 
A

Anonymous

Gast
abgdf schrieb:
war tatsächlich ganz schöne Knobelei ...

Da wird aber auch mit allen Tricks gearbeitet.
Code:
${1+"$@"}
Also die reine Shellinterpretation dieses Ausdruckes: - ist nicht mal in der Manpage von bash beschrieben ;)

Das ist eine Parameter Expansion ähnlich dieser Manpage Beschreibung
${parameter:+word}
Use Alternate Value. If parameter is null or unset, nothing is substituted, otherwise the expansion of word is substituted.
und jetzt kommt die Bösartigkeit. :???: hier wird es ohne das ":" geschrieben und dadurch wird erreicht, dass nur dann nicht substituiert wird, wenn parameter nicht gesetzt ist. parameter darf also durchaus auch einfach leer sein. Und genau das sucht man in der Manpage aber vergebens.

parameter ist in diesem Fall $1 und word $@
also ist die interne Variable 1 (wird ausgelesen mit $1) gesetzt (sie darf auch leer sein), dann wird "$@" genommen, (das sind alle Optionen mit denen das Script gestartet wurde). Ist die Variabe 1 überhaupt nicht gesetzt, wird $@ überhaupt nicht ausgewertet.

robi
 
Oben