verschiedene Fragen zu Funktionen
Beat
- perl
Hallo Ich habe ein paar aktuelle Fragen, weil ich gerade mein Script am Überarbeiten bin.
Voraussetzung: Ich kann meine Scripts nur Online auf einem fernen Server testen, bin also defensiv in der Anwendung von mir noch unbekannten Funktionen.
ERSTE FRAGE
Wann eine Variable mit my deklarieren?
Die zwei unteren Varianten unterscheiden sich,
in Var 1 wird mit einer einzigen Variable gearbeitet
in Var 2 erhalte jedesmal ein frisches neues Array
was ist bessern
bezüglich Speicherverbrauch,
#Variante 1
for (my $1=1 , $i=100 , $i++){
my $link = $i."html";
open(DATENBLATT,"$basedir/$link") || die $! ;
my @main = <DATENBLATT>;
close(DATENBLATT);
# mach was mit @main
}
#Variante 2
my @main;
for (my $1=1 , $i=100 , $i++){
my $link = $i."html";
open(DATENBLATT,"$basedir/$link") || die $! ;
my @main = <DATENBLATT>;
close(DATENBLATT);
# mach was mit @main
}
ZWEITE FRAGE
Ich möchte nun
map()
anstelle von
foreach(){...}
verwenden
my @worklines;
foreach my $lines(@main){
if( $lines =~ /$wort1|$wort2/gi ){push(@worklines, $lines);}
}
würde neu zu :
my @worklines = map( /$wort1|$wort2/gi , @main );
Hierzu auch wieder die Frage, abgesehen dass es sich einfacher schreibt.
Wie verhalten sich map() und foreach() in Bezug auf performance?
Kann ich RegExp in der map Funktion genau gleich anwenden wie mit dem üblichen =~ Operator?
Gibt es eine Seite, die die map() Funktion ausführlich beschreibt
DRITTE FRAGE
Irgendwie liesst man doch viel von Missbrauch durch Bufferoverflows.
Ist es ratsam, dass ich allen Usereingabe Variablen auf maximale Länge kontrolliere?
zum Beispiel:
if (length($userinput) > 1000){&error("Kein normaler User Input");}
danke für Antworten
mfg Beat
Wann eine Variable mit my deklarieren?
Die zwei unteren Varianten unterscheiden sich,
in Var 1 wird mit einer einzigen Variable gearbeitet
in Var 2 erhalte jedesmal ein frisches neues Array
was ist bessern
Die zweite, weil die Variable am Ende des for{}-Blocks out of scope geht und damit nicht mehr den übergeordneten Namespace verunreinigt.
bezüglich Speicherverbrauch,
Der ist in beiden Varianten gleich schlecht.
Stil-Tipp: Nutze den Aufzählungsoperator.
for (1..100) {
my $i = $_;
# tue Zeug mit $i
# $_ lässt sich auch direkt verwenden
};
Wie verhalten sich map() und foreach() in Bezug auf performance?
MJD kommentiert: "Who the fuck cares which one is faster?"
Du kannst für deinen speziellen Fall Benchmarks durchführen und die Ergebnisse vergleichen. Ich persönliche nehme foreach nur im void-Kontext, d.h. die Enumeration liefert nichts zurück; Performance spielt für mich keine Rolle in Perl.
Kann ich RegExp in der map Funktion genau gleich anwenden wie mit dem üblichen =~ Operator?
Ja!
Gibt es eine Seite, die die map() Funktion ausführlich beschreibt
http://perldoc.com/perl5.8.4/pod/func/map.html
Camel book, §3.2.91., §8.4.
Nutshell, §5.93.
Cookbook, §4.15.
Irgendwie liesst man doch viel von Missbrauch durch Bufferoverflows.
Ist es ratsam, dass ich allen Usereingabe Variablen auf maximale Länge kontrolliere?
Perl hat eine eigene Speicherverwaltung für seine Innereien, Bufferoverflows können nicht so wie bei C passieren.
if (length($userinput) > 1000){&error("Kein normaler User Input");}
Das ist aber trotzdem aus Sicherheitsgründen zu empfehlen. Führe immer einen Sanity Check auf Nutzereingaben durch. Wenn du Webprogramme schreibst, ist der Taint Mode unverzichtbar. Details: http://perldoc.com/perl5.8.4/pod/perlsec.html
Stil-Tipp: Verzichte auf & für Funktionen. Nutze den if-Operator bei simplen Entscheidungen.
error("Kein normaler User Input") if length $userinput > 1000;
hi Beat,
der Kollege hat ja schon einiges gesagt.
Hier noch eine kl. Ergänzung von mir.
In letzter Zeit benutze ich für den Zugriff auf Textdateien immer öfter DB_File und DB_RECNO. Das ist nicht so umständlich wie das hantieren mit einem FileHandle, open() und close().
Derzeit baue ich an einem CGI, da brauche ich im gesamten Scriptverlauf den Vollzugriff auf eine Datei. Mit tie() und DB_RECNO binde ich dazu die Datei an ein globales Array (das Array liegt übrigens NICHT im Speicher rum), und wenn das Script zuende ist werden alle am Array gemachten Änderungen zurück in die Datei geschrieben ( untie() ).
Wies geht habch hier mal aufgeschrieben (weiter unten...)
http://perlbase.xwolf.de/cgi-bin/perlbase.cgi?display=16&id=9
Viele Grüße
Rolf
Hy Rolf
DB_File scheint ja mächtig viel Arbeit abzunehmen. Mann muss sich um (fast) keine Formatierung kümmern.
Auch ist es anscheinend so dass ich keine Datei mehr zuerst zum lesen und dann nochmals zum schreiben öffnen muss.
Immerhin lässt sich das ja auch auf normale htmlseiten (als Flatfiles) anwenden
Nur eine Frage noch dazu
wenn mit tie() eine Datei an einen Array/Hash mit dem Modul als Schnittstelle gebunden ist....
dann dürfen anscheinden Manipulationen an dieser gebundenen Variable nur zwischen tie() und untie() stattfinden.
MfG Beat
hi Beat,
wenn mit tie() eine Datei an einen Array/Hash mit dem Modul als Schnittstelle gebunden ist....
dann dürfen anscheinden Manipulationen an dieser gebundenen Variable nur zwischen tie() und untie() stattfinden.
Ganz genau.
Bitte beachte die Flags
O_RDWR|O_CREAT, # lesen, schreiben, ggf, anlegen der Datei
und Berechtigung an Datei
0644 # owner darf alles, alle anderen dürfen nur lesen
0600 # nur der owner darf lesen, schreiben
############## tie() array an datei binden #################
my $filename = 'c:/windows/services';
my @filebody;
tie @filebody, "DB_File", $filename, O_RDWR|O_CREAT, 0644, $DB_RECNO
or die "Cannot open file $filename: $!\n" ;
############## bindung aufheben, Änderungen werden geschrieben
untie @filebody;
exit; # Script ist zuende
Gruss, Rolf
Hallo JAPH
Meine Scripts laufen derzeit mit dem Schalter -w
use strict;
use CGI::Carp qw(fatalsToBrowser);
Ich bin eigentlich immer davon ausgegangen, dass:
use strict
allein schon verhindert dass Eingaben nicht nachträglich interpretiert werden
Wie meine ich das
ohne use strict
Sinput = "wort1|wort2" ;
$finde =~ /$input/;
findet "wort1" oder "wort2"
mit use strict
Sinput = "wort1|wort2" ;
$finde =~ /$input/;
findet "wort1|wort2" , maskiert also die Pipe in der Eingabe
Anyway... werde die perldoc Sicherheits Seite nochmals studieren.
Die Seite zur map() habe ich schon konsultiert.
also mal so
#!/usr/bin/perl -w -T
dies sollte eventuell noch zusätzlich Errormessages schreiben (denke ich)
mfg Beat
Ich bin eigentlich immer davon ausgegangen, dass:
use strict
allein schon verhindert dass Eingaben nicht nachträglich interpretiert werden
Wer hat dir denn diesen Floh ins Ohr gesetzt? :)
strict macht folgendes: http://perldoc.com/perl5.8.4/lib/strict.html
Wie meine ich das
ohne use strict
Sinput = "wort1|wort2" ;
$finde =~ /$input/;
findet "wort1" oder "wort2"mit use strict
Sinput = "wort1|wort2" ;
$finde =~ /$input/;
findet "wort1|wort2" , maskiert also die Pipe in der Eingabe
Das ist Murks. Ich habe mal einen Testcase gebaut:
use strict;
my $muster = 'wort1|wort2';
my $vergleich1 = 'abcwort1xyz';
my $vergleich2 = 'abcwort2xyz';
my $vergleich3 = 'abcwort1|wort2xyz';
print "true1\n" if $vergleich1 =~ /$muster/; # ist wahr
print "true2\n" if $vergleich2 =~ /$muster/; # ist auch wahr
print "true3\n" if $vergleich3 =~ /$muster/; # dito
Dieser verhält sich mit oder ohne strict identisch. Ich glaube, was du suchst, ist quotemeta.
use strict;
my $muster = 'Guten Tag.';
my $vergleich1 = 'abcGuten Tag0xyz';
my $vergleich2 = 'abcGuten Tag.xyz';
print "true1\n" if $vergleich1 =~ /$muster/; # ist wahr
print "true2\n" if $vergleich2 =~ /$muster/; # ist auch wahr
my $musterquoted = quotemeta $muster;
print "true1\n" if $vergleich1 =~ /$musterquoted/; # ist falsch!
print "true2\n" if $vergleich2 =~ /$musterquoted/; # wahr
print "true1\n" if $vergleich1 =~ /\Q$muster\E/; # ist falsch!
print "true2\n" if $vergleich2 =~ /\Q$muster\E/; # wahr
Erläuterung: Im ersten Abschnitt trifft die Übereinstimmung auf beide Strings zu, denn der Punkt am Ende wird als reguläres Zeichen gewertet. Im zweiten und dritten Abschnitt trifft die Übereinstimmung nur noch auf String 2 zu, denn der Punkt wird als literales Zeichen, d.h. als tatsächlicher Punkt, gewertet. Quotemeta tut Backslashes vor reguläre Zeichen und raubt ihnen damit ihren Sonderstatus.
Ooops
Erst mal danke..... man hat selten jemanden, der gleich testet.
Aber mir ist folgendes aufgefallen:
Bei mir
Sinput = "wort1|wort2" ;
Doppelte Anführungszeichen
In deinem Experiment
my $muster = 'wort1|wort2';
einfache Anführungszeichen, und das hat doch einen Einfluss
Und der springende (oder doch bemerkenswerte) Punkt.
auch in deinem Beispiel wird ein Punkt als Platzhalter interpretiert. (was mich wiederum überrascht)
Das bedeutet, Benutzereingaben können eine RegExp doch mit seltsamen Sachen füttern, wobei man nur hoffen kann dass nicht ein ///e (Also eine evaluierte Regexp) gefüttert wird.
Ich denke ich werde die Eigaben mit dem quotemeta Befehl bearbeiten, und mal schauen was mein -T parameter sonst noch meldet.
mfg Beat