Perl Language
Lecture du contenu d'un fichier dans une variable
Recherche…
La manière manuelle
open my $fh, '<', $filename
or die "Could not open $filename for reading: $!";
my $contents = do { local $/; <$fh> };
Après avoir ouvert le fichier (read man perlio
si vous voulez lire des codages de fichiers spécifiques au lieu d'octets bruts), l'astuce est dans le bloc do
: <$fh>
, le descripteur de fichier dans un opérateur de diamant, renvoie un enregistrement unique . La variable "séparateur d'enregistrements en entrée" $/
spécifie ce qu'est un "enregistrement" - par défaut, il est défini sur un caractère de nouvelle ligne afin que "un enregistrement" signifie "une seule ligne". Comme $/
est une variable globale, local
fait deux choses: il crée une copie locale temporaire de $/
qui disparaît à la fin du bloc et lui donne la valeur (non) undef
(la "valeur" que Perl donne aux variables non initialisées). Lorsque le séparateur d'enregistrements en entrée possède cette valeur (non), l'opérateur de diamant retourne le fichier entier. (Il considère le fichier entier comme une seule ligne.)
A l'aide de do
, vous pouvez même ouvrir manuellement un fichier. Pour la lecture répétée de fichiers,
sub readfile { do { local(@ARGV,$/) = $_[0]; <> } }
my $content = readfile($filename);
peut être utilisé. Ici, une autre variable globale ( @ARGV
) est localisée pour simuler le même processus utilisé lors du démarrage d'un script perl avec des paramètres. $/
est toujours undef
, puisque le tableau devant "mange" tous les arguments entrants. Ensuite, l'opérateur de diamant <>
fournit à nouveau un enregistrement défini par $/
(le fichier entier) et retourne du bloc do
, qui à son tour retourne du sous-fichier.
Le sous n'a pas de gestion explicite des erreurs, ce qui est une mauvaise pratique! Si une erreur survient lors de la lecture du fichier, vous recevrez undef
comme valeur de retour, par opposition à une chaîne vide provenant d'un fichier vide.
Un autre inconvénient du dernier code est le fait que vous ne pouvez pas utiliser PerlIO pour différents encodages de fichiers - vous obtenez toujours des octets bruts.
Path :: Tiny
Utiliser l'idiome de The Manual Way à plusieurs reprises dans un script devient vite fastidieux. Vous pouvez donc essayer un module.
use Path::Tiny;
my $contents = path($filename)->slurp;
Vous pouvez passer une option binmode
si vous avez besoin de contrôler les encodages de fichiers, les fins de ligne, etc. - voir man perlio
:
my $contents = path($filename)->slurp( {binmode => ":encoding(UTF-8)"} );
Path::Tiny
également beaucoup d'autres fonctions pour gérer les fichiers, ce qui en fait un bon choix.
Fichier :: Slurper
C'est un module minimaliste qui ne fait que glisser des fichiers en variables, rien d’autre.
use File::Slurper 'read_text';
my $contents = read_text($filename);
read_text()
prend deux paramètres facultatifs pour spécifier le codage du fichier et si les fins de ligne doivent être traduites entre les normes unixish LF ou DOSish CRLF:
my $contents = read_text($filename, 'UTF-8', 1);
Fichier :: Slurp
Ne l'utilise pas Bien qu'il existe depuis longtemps et soit toujours le module que la plupart des programmeurs suggéreront, il est cassé et il est peu probable qu'il soit corrigé .
Insertion d'un fichier dans une variable de tableau
open(my $fh, '<', "/some/path") or die $!;
my @ary = <$fh>;
Lorsqu'il est évalué dans un contexte de liste, l'opérateur de diamant renvoie une liste composée de toutes les lignes du fichier (dans ce cas, le résultat est attribué à un contexte de liste de fournitures de tableau). Le terminateur de ligne est conservé et peut être supprimé en chomping:
chomp(@ary); #removes line terminators from all the array elements.
Fichier Slurp en un trait
Le séparateur d'enregistrement en entrée peut être spécifié avec l'option -0
( zéro , pas de majuscule O ). Il prend un nombre octal ou hexadécimal comme valeur. Toute valeur supérieure ou égale à 0400
entraînera la perte de fichiers Perl, mais par convention, la valeur utilisée à cette fin est 0777
.
perl -0777 -e 'my $file = <>; print length($file)' input.txt
En allant plus loin avec le minimalisme, en spécifiant l'option -n
Perl lit automatiquement chaque ligne (dans notre cas - le fichier entier) dans la variable $_
.
perl -0777 -ne 'print length($_)' input.txt