Ich versuche, eine HTML-Datei als eine große lange Zeichenfolge zu öffnen. Das habe ich:
open(FILE, 'index.html') or die "Can't read file 'filename' [$!]\n";
$document = <FILE>;
close (FILE);
print $document;
was in ... endet:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN
Ich möchte jedoch, dass das Ergebnis wie folgt aussieht:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
Auf diese Weise kann ich das gesamte Dokument einfacher durchsuchen.
Antworten:
Hinzufügen:
vor dem Lesen aus dem Dateihandle. Siehe Wie kann ich eine ganze Datei auf einmal einlesen? , oder
Siehe Variablen zu Dateihandles in
perldoc perlvar
undperldoc -f local
.Wenn Sie Ihr Skript auf den Server stellen können, können Sie übrigens alle gewünschten Module haben. Siehe Wie behalte ich mein eigenes Modul- / Bibliotheksverzeichnis? .
Darüber hinaus können Sie mit Path :: Class :: File schlürfen und spucken .
Pfad :: Tiny gibt noch mehr Komfort Methoden wie
slurp
,slurp_raw
,slurp_utf8
sowie derenspew
Pendants.quelle
$/
, sollten Sie wahrscheinlich Links für weitere Informationen hinzufügen.local
und nichtmy
.Ich würde es so machen:
Beachten Sie die Verwendung der Drei-Argument-Version von open. Es ist viel sicherer als die alten Versionen mit zwei (oder einem) Argumenten. Beachten Sie auch die Verwendung eines lexikalischen Dateihandles. Lexikalische Dateihandles sind aus vielen Gründen schöner als die alten Bareword-Varianten. Wir nutzen hier einen davon: Sie schließen, wenn sie den Rahmen verlassen.
quelle
Mit File :: Slurp :
Ja, auch Sie können CPAN verwenden .
quelle
Can't locate File/Slurp.pm in @INC (@INC contains: /usr/lib/perl5/5.8/msys
:(Alle Beiträge sind leicht nicht idiomatisch. Die Redewendung lautet:
Meistens muss $ / nicht festgelegt werden
undef
.quelle
local $foo = undef
ist nur die von Perl Best Practice (PBP) vorgeschlagene Methode. Wenn wir Codefragmente veröffentlichen, würde ich denken, dass es eine gute Sache wäre, unser Bestes zu geben, um dies klar zu machen.Von perlfaq5: Wie kann ich eine ganze Datei auf einmal einlesen? ::
Sie können das File :: Slurp-Modul verwenden, um dies in einem Schritt zu tun.
Der übliche Perl-Ansatz zum Verarbeiten aller Zeilen in einer Datei besteht darin, dies zeilenweise zu tun:
Dies ist enorm effizienter, als die gesamte Datei als Zeilenarray in den Speicher einzulesen und dann Element für Element zu verarbeiten, was häufig - wenn nicht fast immer - der falsche Ansatz ist. Wann immer Sie jemanden sehen, tun Sie Folgendes:
Sie sollten lange und gründlich darüber nachdenken, warum Sie alles auf einmal laden müssen. Es ist einfach keine skalierbare Lösung. Möglicherweise macht es auch mehr Spaß, das Standardmodul Tie :: File oder die $ DB_RECNO-Bindungen des DB_File-Moduls zu verwenden, mit denen Sie ein Array an eine Datei binden können, sodass das Array beim Zugriff auf ein Element tatsächlich auf die entsprechende Zeile in der Datei zugreift .
Sie können den gesamten Inhalt des Dateihandles in einen Skalar einlesen.
Dadurch wird Ihr Datensatztrennzeichen vorübergehend deaktiviert, und die Datei wird beim Blockausgang automatisch geschlossen. Wenn die Datei bereits geöffnet ist, verwenden Sie einfach Folgendes:
Für normale Dateien können Sie auch die Lesefunktion verwenden.
Das dritte Argument testet die Bytegröße der Daten im INPUT-Dateihandle und liest so viele Bytes in den Puffer $ var.
quelle
Ein einfacher Weg ist:
Eine andere Möglichkeit besteht darin, das Trennzeichen für den Eingabedatensatz "$ /" zu ändern. Sie können dies lokal in einem leeren Block tun, um zu vermeiden, dass das globale Datensatztrennzeichen geändert wird.
quelle
{local $/; open(my $f, '<', 'filename'); $d = <$f>;}
open
oder die implizit aufgerufene nicht überprüftclose
.my $d = do{ local $/; open(my $f, '<', 'filename') or die $!; my $tmp = <$f>; close $f or die $!; $tmp}
. (Das hat immer noch das Problem, dass es die Eingabecodierung nicht spezifiziert.)use autodie
Die Hauptverbesserung, die ich zeigen wollte, war das lexikalische Dateihandle und das 3-Arg-Open. Gibt es einen Grund, warum Sie dasdo
tun? Warum nicht einfach die Datei in eine Variable ausgeben, die vor dem Block deklariert wurde?Entweder Satz
$/
anundef
(jrockway Antwort sehen) oder verketten nur alle Zeilen der Datei:Es wird empfohlen, Skalare für Dateihandles in jeder Perl-Version zu verwenden, die dies unterstützt.
quelle
Ein anderer möglicher Weg:
quelle
Sie erhalten nur die erste Zeile vom Diamantoperator,
<FILE>
weil Sie sie im skalaren Kontext auswerten:Im Listen- / Array-Kontext gibt der Diamantoperator alle Zeilen der Datei zurück.
quelle
<=>
und der<>
ist der Diamantoperator.Ich würde es auf einfachste Weise tun, damit jeder verstehen kann, was passiert, auch wenn es intelligentere Wege gibt:
quelle
<f>
- gibt ein Array von Zeilen aus unserer Datei zurück (falls$/
der Standardwert vorliegt"\n"
) undjoin ''
steckt dieses Array dann in.quelle
Dies ist eher ein Vorschlag, wie man es NICHT macht. Ich hatte gerade eine schlechte Zeit, einen Fehler in einer ziemlich großen Perl-Anwendung zu finden. Die meisten Module hatten eigene Konfigurationsdateien. Um die Konfigurationsdateien als Ganzes zu lesen, habe ich diese einzelne Perl-Zeile irgendwo im Internet gefunden:
Der Zeilentrenner wird wie zuvor erläutert neu zugewiesen. Es ordnet aber auch den STDIN neu zu.
Dies hatte mindestens einen Nebeneffekt, dessen Suche mich Stunden gekostet hat: Das implizite Dateihandle wird nicht ordnungsgemäß geschlossen (da es überhaupt nicht aufgerufen wird
close
).Zum Beispiel:
Ergebnisse in:
Das Seltsame ist, dass der Zeilenzähler
$.
für jede Datei um eins erhöht wird. Es wird nicht zurückgesetzt und enthält nicht die Anzahl der Zeilen. Und es wird beim Öffnen einer anderen Datei nicht auf Null zurückgesetzt, bis mindestens eine Zeile gelesen wurde. In meinem Fall habe ich so etwas gemacht:Aufgrund dieses Problems war die Bedingung falsch, da der Zeilenzähler nicht ordnungsgemäß zurückgesetzt wurde. Ich weiß nicht, ob dies ein Fehler oder einfach ein falscher Code ist ... Auch das Aufrufen von
close;
oderclose STDIN;
hilft nicht.Ich habe diesen unlesbaren Code durch Öffnen, Verketten von Zeichenfolgen und Schließen ersetzt. Die von Brad Gilbert veröffentlichte Lösung funktioniert jedoch auch, da stattdessen ein explizites Dateihandle verwendet wird.
Die drei Zeilen am Anfang können ersetzt werden durch:
Dadurch wird das Dateihandle ordnungsgemäß geschlossen.
quelle
Verwenden
vorher
$document = <FILE>;
.$/
ist das Trennzeichen für Eingabedatensätze , bei dem es sich standardmäßig um eine neue Zeile handelt. Wennundef
Sie es neu definieren, sagen Sie, dass es kein Feldtrennzeichen gibt. Dies wird als "Slurp" -Modus bezeichnet.Andere Lösungen wie
undef $/
undlocal $/
(aber nichtmy $/
) deklarieren $ / und erzeugen somit den gleichen Effekt.quelle
Sie können einfach eine Unterroutine erstellen:
quelle
Ich weiß nicht, ob es eine gute Praxis ist, aber ich habe diese verwendet:
quelle
Das sind alles gute Antworten. ABER wenn Sie sich faul fühlen und die Datei nicht so groß ist und die Sicherheit kein Problem darstellt (Sie wissen, dass Sie keinen verdorbenen Dateinamen haben), können Sie Folgendes berappen:
quelle
Sie können cat unter Linux verwenden:
quelle