GoGPT Best VPN GoSearch

Icône de favori OnWorks

perlfaq5 - En ligne dans le Cloud

Exécutez perlfaq5 dans le fournisseur d'hébergement gratuit OnWorks sur Ubuntu Online, Fedora Online, l'émulateur en ligne Windows ou l'émulateur en ligne MAC OS

Il s'agit de la commande perlfaq5 qui peut être exécutée dans le fournisseur d'hébergement gratuit OnWorks en utilisant l'un de nos multiples postes de travail en ligne gratuits tels que Ubuntu Online, Fedora Online, l'émulateur en ligne Windows ou l'émulateur en ligne MAC OS

PROGRAMME:

Nom


perlfaq5 - Fichiers et formats

VERSION


Version 5.021009

DESCRIPTION


Cette section traite des E/S et des problèmes "f" : descripteurs de fichiers, vidage, formats et
pieds de page.

Comment la do I rincer/détamponner an sortie descripteur de fichier ? Pourquoi Choisir doit I do ?
(contribution de brian d foy)

Vous aimerez peut-être lire « Suffering From Buffering » de Mark Jason Dominus sur
<http://perl.plover.com/FAQs/Buffering.html>.

Perl met normalement en mémoire tampon la sortie afin qu'il ne fasse pas d'appel système pour chaque bit de sortie. Par
économisant la production, il fait moins d'appels système coûteux. Par exemple, dans ce petit
de code, vous voulez imprimer un point à l'écran pour chaque ligne que vous traitez pour regarder le
progression de votre programme. Au lieu de voir un point pour chaque ligne, Perl met en mémoire tampon la sortie
et vous avez une longue attente avant de voir une rangée de 50 points à la fois :

# longue attente, puis rangée de points en même temps
tandis que( <> ) {
imprimer ".";
imprime "\n" à moins que ++$count % 50 ;

#... opérations de traitement en ligne coûteuses
}

Pour contourner ce problème, vous devez débuffer le descripteur de fichier de sortie, dans ce cas, "STDOUT".
Vous pouvez définir la variable spéciale $| à une valeur vraie (mnémonique : rendre vos descripteurs de fichiers
"brûlant"):

$|++ ;

# point affiché immédiatement
tandis que( <> ) {
imprimer ".";
imprime "\n" à moins que ++$count % 50 ;

#... opérations de traitement en ligne coûteuses
}

Le $| est l'une des variables spéciales par descripteur de fichier, donc chaque descripteur de fichier a sa propre copie
de sa valeur. Si vous souhaitez fusionner la sortie standard et l'erreur standard par exemple, vous
doivent débuffer chacun (bien que STDERR puisse être non tamponné par défaut) :

{
my $previous_default = select(STDOUT); # enregistrer la valeur par défaut précédente
$|++ ; # autoflush STDOUT
sélectionner(STDERR);
$|++ ; # autoflush STDERR, pour être sûr
select($previous_default); # restaurer la valeur par défaut précédente
}

# devrait maintenant alterner . et +
tandis que ( 1 ) {
dormir 1 ;
print STDOUT ".";
imprimer STDERR "+" ;
imprime STDOUT "\n" à moins que ++$count % 25 ;
}

Outre le $| variable spéciale, vous pouvez utiliser "binmode" pour donner à votre descripteur de fichier un ":unix"
couche, qui n'est pas tamponnée :

binmode( STDOUT, ":unix" );

tandis que ( 1 ) {
dormir 1 ;
imprimer ".";
imprime "\n" à moins que ++$count % 50 ;
}

Pour plus d'informations sur les couches de sortie, consultez les entrées pour "binmode" et ouvrez dans perlfunc,
et la documentation du module PerlIO.

Si vous utilisez IO::Handle ou l'une de ses sous-classes, vous pouvez appeler la méthode "autoflush"
pour modifier les paramètres du descripteur de fichier :

utiliser IO::Handle;
ouvrir my( $io_fh ), ">", "output.txt" ;
$io_fh->rinçage automatique(1);

Les objets IO::Handle ont également une méthode "flush". Vous pouvez vider le tampon à tout moment
voulez sans mise en mémoire tampon automatique

$io_fh->flush ;

Comment la do I changement, effacer, or insérer a en ligne in a fichier, or ajouter à le début of a fichier?
(contribution de brian d foy)

L'idée de base d'insérer, de modifier ou de supprimer une ligne d'un fichier texte implique
lire et imprimer le fichier jusqu'au point où vous souhaitez effectuer la modification, effectuer la modification,
puis lire et imprimer le reste du fichier. Perl ne fournit pas d'accès aléatoire à
lignes (d'autant plus que le séparateur d'entrée d'enregistrement, $/, est modifiable), bien que des modules tels
comme Tie::Le fichier peut le truquer.

Un programme Perl pour effectuer ces tâches prend la forme de base d'ouverture d'un fichier, d'impression de son
lignes, puis en fermant le fichier :

ouvrir mon $in, '<', $file ou mourir "Impossible de lire l'ancien fichier : $!";
ouvrir mon $out, '>', "$file.new" ou mourir "Impossible d'écrire un nouveau fichier : $!" ;

while( <$in> ) {
affiche $out $_;
}

fermer $out;

Dans ce formulaire de base, ajoutez les parties dont vous avez besoin pour insérer, modifier ou supprimer des lignes.

Pour ajouter des lignes au début, imprimez ces lignes avant d'entrer dans la boucle qui imprime
les lignes existantes.

ouvrir mon $in, '<', $file ou mourir "Impossible de lire l'ancien fichier : $!";
ouvrir mon $out, '>', "$file.new" ou mourir "Impossible d'écrire un nouveau fichier : $!" ;

print $out "# Ajouter cette ligne en haut\n" ; # <--- VOICI LA MAGIE

while( <$in> ) {
affiche $out $_;
}

fermer $out;

Pour modifier les lignes existantes, insérez le code pour modifier les lignes à l'intérieur de la boucle "while". Dans
dans ce cas, le code trouve toutes les versions minuscules de "perl" et les met en majuscules. Les
se produit pour chaque ligne, alors assurez-vous que vous êtes censé le faire sur chaque ligne !

ouvrir mon $in, '<', $file ou mourir "Impossible de lire l'ancien fichier : $!";
ouvrir mon $out, '>', "$file.new" ou mourir "Impossible d'écrire un nouveau fichier : $!" ;

print $out "# Ajouter cette ligne en haut\n" ;

while( <$in> ) {
s/\b(perl)\b/Perl/g;
affiche $out $_;
}

fermer $out;

Pour modifier uniquement une ligne particulière, le numéro de ligne d'entrée, $., est utile. Première lecture et
imprimez les lignes jusqu'à celle que vous souhaitez modifier. Ensuite, lisez la seule ligne que vous voulez
changez-le, changez-le et imprimez-le. Après cela, lisez le reste des lignes et imprimez celles-ci :

while( <$in> ) { # imprime les lignes avant le changement
affiche $out $_;
dernier si $. == 4; # numéro de ligne avant modification
}

ma ligne $ = <$in> ;
$ligne =~ s/\b(perl)\b/Perl/g;
imprimer $out $line ;

while( <$in> ) { # imprime le reste des lignes
affiche $out $_;
}

Pour sauter des lignes, utilisez les commandes de bouclage. Le "suivant" dans cet exemple saute les lignes de commentaire,
et le "dernier" arrête tout traitement une fois qu'il rencontre "__END__" ou "__DATA__".

while( <$in> ) {
suivant si /^\s+#/; # sauter les lignes de commentaire
last if /^__(END|DATA)__$/; # arrêt à la fin du marqueur de code
affiche $out $_;
}

Faites le même genre de chose pour supprimer une ligne particulière en utilisant "suivant" pour sauter les lignes
vous ne voulez pas apparaître dans la sortie. Cet exemple saute une ligne sur cinq :

while( <$in> ) {
suivant à moins que $. % 5 ;
affiche $out $_;
}

Si, pour une raison quelconque, vous voulez vraiment voir tout le fichier à la fois plutôt que
traitement ligne par ligne, vous pouvez l'insérer (tant que vous pouvez tout mettre dans
Mémoire!):

ouvrir mon $in, '<', $file ou mourir "Impossible de lire l'ancien fichier : $!"
ouvrir mon $out, '>', "$file.new" ou mourir "Impossible d'écrire un nouveau fichier : $!" ;

mon $content = do { local $/; <$dans> } ; # slurp !

# faites votre magie ici

imprimer $out $content;

Des modules tels que Path::Tiny et Tie::File peuvent également vous aider. Si vous pouvez, cependant,
évitez de lire tout le fichier à la fois. Perl ne rendra pas cette mémoire à l'opérateur
système jusqu'à la fin du processus.

Vous pouvez également utiliser des one-liners Perl pour modifier un fichier sur place. Ce qui suit change tout
'Fred' à 'Barney' dans dansFichier.txt, en écrasant le fichier avec le nouveau contenu. Avec le
commutateur "-p", Perl enroule une boucle "while" autour du code que vous spécifiez avec "-e" et "-i"
active l'édition sur place. La ligne courante est en $_. Avec "-p", Perl imprime automatiquement
la valeur de $_ à la fin de la boucle. Voir perlrun pour plus de détails.

perl -pi -e 's/Fred/Barney/' inFile.txt

Pour faire une sauvegarde de "inFile.txt", donnez à "-i" une extension de fichier à ajouter :

perl -pi.bak -e 's/Fred/Barney/' inFile.txt

Pour modifier uniquement la cinquième ligne, vous pouvez ajouter un test vérifiant $., le numéro de la ligne d'entrée, puis
n'effectuez l'opération que lorsque le test est réussi :

perl -pi -e 's/Fred/Barney/ if $. == 5' dansFichier.txt

Pour ajouter des lignes avant une certaine ligne, vous pouvez ajouter une ligne (ou des lignes !) avant que Perl n'imprime $_ :

perl -pi -e 'print "Mettre avant la troisième ligne\n" si $. == 3' dansFichier.txt

Vous pouvez même ajouter une ligne au début d'un fichier, puisque la ligne courante s'imprime au
fin de boucle :

perl -pi -e 'print "Mettre avant la première ligne\n" si $. == 1' dansFichier.txt

Pour insérer une ligne après celle déjà présente dans le fichier, utilisez le commutateur "-n". C'est comme "-p"
sauf qu'il n'affiche pas $_ à la fin de la boucle, vous devez donc le faire vous-même.
Dans ce cas, imprimez d'abord $_, puis imprimez la ligne que vous souhaitez ajouter.

perl -ni -e 'impression; print "A mettre après la cinquième ligne\n" si $. == 5' dansFichier.txt

Pour supprimer des lignes, n'imprimez que celles que vous souhaitez.

perl -ni -e 'imprimer si /d/' dansFichier.txt

Comment la do I compter le nombre of lignes in a fichier?
(contribution de brian d foy)

Conceptuellement, le moyen le plus simple de compter les lignes d'un fichier est simplement de les lire et de
compte les:

mon compte $ = 0 ;
while( <$fh> ) { $count++; }

Vous n'avez pas vraiment besoin de les compter vous-même, cependant, puisque Perl le fait déjà avec
le $. variable, qui est le numéro de ligne actuel du dernier descripteur de fichier lu :

1 while( <$fh> );
mon $compte = $.;

Si vous souhaitez utiliser $., vous pouvez le réduire à une simple ligne, comme l'une de celles-ci :

% perl -lne '} print $.; {' déposer

% perl -lne 'END { print $. }' déposer

Ceux-ci peuvent être assez inefficaces cependant. S'ils ne sont pas assez rapides pour vous, vous pourriez simplement
lire des morceaux de données et compter le nombre de nouvelles lignes :

mes $lignes = 0 ;
open my($fh), '<:raw', $filename ou die "Impossible d'ouvrir $filename: $!";
tandis que( sysread $fh, $buffer, 4096 ) {
$lines += ( $buffer =~ tr/\n// );
}
fermer $fh ;

Cependant, cela ne fonctionne pas si la fin de ligne n'est pas une nouvelle ligne. Tu pourrais changer ça
"tr///" à un "s///" afin que vous puissiez compter le nombre de fois que le séparateur d'enregistrement d'entrée, $/,
révéler:

mes $lignes = 0 ;
open my($fh), '<:raw', $filename ou die "Impossible d'ouvrir $filename: $!";
tandis que( sysread $fh, $buffer, 4096 ) {
$lignes += ( $buffer =~ s|$/||g; );
}
fermer $fh ;

Si cela ne vous dérange pas, la commande "wc" est généralement la plus rapide, même avec le
surcharge interprocessus supplémentaire. Assurez-vous cependant que vous avez un nom de fichier intact :

#!perl-T

$ENV{CHEMIN} = undef;

mes lignes $;
if( $filename =~ /^([0-9a-z_.]+)\z/ ) {
$lignes = `/usr/bin/wc -l$1`
écraser les lignes ;
}

Comment la do I delete le dernier N lignes grâce au a fichier?
(contribution de brian d foy)

La solution conceptuelle la plus simple consiste à compter les lignes dans le fichier puis à commencer par le
début et imprimez le nombre de lignes (moins le dernier N) dans un nouveau fichier.

Le plus souvent, la vraie question est de savoir comment supprimer les N dernières lignes sans en faire plus
qu'un seul passage sur le fichier, ou comment le faire sans trop de copier. Le concept facile est
la dure réalité quand vous pourriez avoir des millions de lignes dans votre fichier.

Une astuce consiste à utiliser File::ReadBackwards, qui commence à la fin du fichier. Ce module
fournit un objet qui enveloppe le vrai descripteur de fichier pour vous permettre de vous déplacer facilement
le fichier. Une fois que vous arrivez à l'endroit dont vous avez besoin, vous pouvez obtenir le véritable gestionnaire de fichier et travailler
avec lui comme d'habitude. Dans ce cas, vous obtenez la position du fichier à la fin de la dernière ligne que vous
souhaitez conserver et tronquer le fichier jusqu'à ce point :

utilisez File::ReadBackwards;

mon $filename = 'test.txt';
mon $Lines_to_truncate = 2 ;

my $bw = File::ReadBackwards->new( $filename )
ou die "Impossible de lire à l'envers dans [$filename] : $!";

mon $lines_from_end = 0 ;
jusqu'à( $bw->eof ou $lines_from_end == $Lines_to_truncate ) {
print « Got : », $bw->readline ;
$lines_from_end++ ;
}

truncate( $filename, $bw->tell );

Le module File::ReadBackwards a aussi l'avantage de paramétrer l'enregistrement d'entrée
séparateur à une expression régulière.

Vous pouvez également utiliser le module Tie::File qui vous permet d'accéder aux lignes via un lien
déployer. Vous pouvez utiliser des opérations de tableau normales pour modifier votre fichier, y compris la définition du dernier
index et en utilisant "splice".

Comment la Vous pouvez I utilisé De Perl "-JE" option grâce au dans les a programme?
"-i" définit la valeur de la variable $^I de Perl, qui à son tour affecte le comportement de "<>" ;
voir perlrun pour plus de détails. En modifiant directement les variables appropriées, vous pouvez obtenir
le même comportement dans un programme plus vaste. Par exemple:

#...
{
local($^I, @ARGV) = ('.orig', glob("*.c"));
tandis que (<>) {
si ($. == 1) {
print "Cette ligne doit apparaître en haut de chaque fichier\n" ;
}
s/\b(p)earl\b/${1}erl/i ; # Corriger les fautes de frappe, en préservant la casse
imprimer;
fermer ARGV si eof; # Réinitialiser $.
}
}
# $^I et @ARGV reviennent à leurs anciennes valeurs ici

Ce bloc modifie tous les fichiers ".c" du répertoire courant en laissant une sauvegarde du
données d'origine de chaque fichier dans un nouveau fichier ".c.orig".

Comment la Vous pouvez I copier a fichier?
(contribution de brian d foy)

Utilisez le module Fichier::Copier. Il est fourni avec Perl et peut faire une copie conforme sur tous les systèmes de fichiers,
et il fait sa magie de manière portable.

utiliser Fichier::Copier;

copy( $original, $new_copy ) ou die "Échec de la copie : $!" ;

Si vous ne pouvez pas utiliser File::Copy, vous devrez faire le travail vous-même : ouvrez le fichier original,
ouvrez le fichier de destination, puis imprimez vers le fichier de destination pendant que vous lisez l'original.
Vous devez également vous rappeler de copier les autorisations, le propriétaire et le groupe dans le nouveau fichier.

Comment la do I a prendre une a temporaire filet prénom?
Si vous n'avez pas besoin de connaître le nom du fichier, vous pouvez utiliser "open()" avec "undef" en place
du nom de fichier. Dans Perl 5.8 ou supérieur, la fonction "open()" crée un fichier anonyme
Fichier temporaire:

ouvrir mon $tmp, '+>', undef ou mourir $!;

Sinon, vous pouvez utiliser le module File::Temp.

utilisez File::Temp qw/ tempfile tempdir /;

mon $dir = tempdir( CLEANUP => 1 );
($fh, $filename) = tempfile( DIR => $dir );

# ou si vous n'avez pas besoin de connaître le nom du fichier

mon $fh = fichier temporaire( DIR => $dir );

Le File::Temp est un module standard depuis Perl 5.6.1. Si vous n'avez pas de moderne
suffisamment de Perl installé, utilisez la méthode de classe "new_tmpfile" du module IO::File pour obtenir
un descripteur de fichier ouvert pour la lecture et l'écriture. Utilisez-le si vous n'avez pas besoin de connaître le fichier
nom:

utiliser IO::Fichier ;
mon $fh = IO::File->new_tmpfile()
ou die "Impossible de créer un nouveau fichier temporaire : $ !" ;

Si vous vous engagez à créer un fichier temporaire à la main, utilisez l'ID de processus et/ou le
valeur de temps actuelle. Si vous avez besoin d'avoir plusieurs fichiers temporaires en un seul processus, utilisez un
compteur:

COMMENCER {
utilisez Fcntl ;
utiliser File::Spec;
my $temp_dir = File::Spec->tmpdir();
my $file_base = sprintf "%d-%d-0000", $$, heure ;
my $base_name = File::Spec->catfile($temp_dir, $file_base);

sous-fichier_temp {
mon $fh;
mon compte $ = 0 ;
jusqu'à( défini(fileno($fh)) || $count++ > 100 ) {
$base_name =~ s/-(\d+)$/"-" . (1 + 1 $)/e ;
# O_EXCL est requis pour des raisons de sécurité.
sysopen $fh, $base_name, O_WRONLY|O_EXCL|O_CREAT ;
}

if( défini fileno($fh) ) {
return ($fh, $base_name);
}
else {
revenir ();
}
}
}

Comment la Vous pouvez I manipuler longueur d'enregistrement fixe fichiers?
Le moyen le plus efficace est d'utiliser paquet() et déballer(). C'est plus rapide que d'utiliser substr ()
en prenant beaucoup, beaucoup de chaînes. Il est plus lent pour quelques-uns.

Voici un échantillon de code à décomposer et à reconstituer du format fixe
lignes d'entrée, dans ce cas à partir de la sortie d'un ps normal de style Berkeley :

# exemple de ligne d'entrée :
# 15158 p5 T 0:00 perl /home/tchrist/scripts/maintenant-quoi
mon $PS_T = 'A6 A4 A7 A5 A*';
ouvrir mon $ps, '-|', 'ps' ;
imprimer le scalaire <$ps> ;
my @fields = qw( commande pid tt stat time );
tandis que (<$ps>) {
mon %processus;
@process{@fields} = décompresser($PS_T, $_);
pour mon $field ( @fields ) {
print "$field : <$process{$field}>\n" ;
}
print 'line=', pack($PS_T, @process{@fields} ), "\n" ;
}

Nous avons utilisé une tranche de hachage afin de gérer facilement les champs de chaque ligne. Stockage du
les touches d'un tableau facilitent leur utilisation en tant que groupe ou en boucle sur elles avec "for".
Cela évite également de polluer le programme avec des variables globales et l'utilisation de références symboliques.

Comment la Vous pouvez I a prendre une a descripteur de fichier locales à a sous-programme ? Comment la do I pass descripteurs de fichiers jusqu'à XNUMX fois
sous-programmes? Comment la do I a prendre une an tableau of descripteurs de fichiers ?
Depuis perl5.6, ouvrir() autovivifie les descripteurs de fichiers et de répertoires en tant que références si vous les transmettez
une variable scalaire non initialisée. Vous pouvez ensuite passer ces références comme n'importe quel autre
scalaire et utilisez-les à la place des descripteurs nommés.

ouvrir mon $fh, $file_name ;

ouvrir local $fh, $file_name ;

print $fh "Bonjour tout le monde !\n" ;

fichier_processus( $fh );

Si vous le souhaitez, vous pouvez stocker ces descripteurs de fichiers dans un tableau ou un hachage. Si vous y accédez
directement, ce ne sont pas de simples scalaires et vous devez donner un petit coup de pouce à "print" en plaçant
la référence du descripteur de fichier entre accolades. Perl ne peut le comprendre par lui-même que lorsque le
référence de descripteur de fichier est un simple scalaire.

mon @fhs = ( $fh1, $fh2, $fh3 );

for( $i = 0; $i <= $#fhs; $i++ ) {
print {$fhs[$i]} "juste une autre réponse Perl, \n" ;
}

Avant perl5.6, vous deviez gérer divers idiomes de typeglob que vous pouviez voir dans les anciens
code.

ouvrir FICHIER, "> $nomfichier" ;
processus_typeglob( *FILE );
référence_processus( \*FILE );

sub process_typeglob { local *FH = shift; print FH "Typeglob !" }
sub process_reference { local $fh = shift; print $fh "Référence !" }

Si vous souhaitez créer de nombreuses poignées anonymes, vous devriez vérifier le symbole ou
IO::Gérer les modules.

Comment la Vous pouvez I utilisé a descripteur de fichier indirectement?
Un descripteur de fichier indirect est l'utilisation de quelque chose d'autre qu'un symbole à un endroit qu'un
le handle de fichier est attendu. Voici des moyens d'obtenir des descripteurs de fichiers indirects :

$fh = SOME_FH; # bareword est strict-subs hostile
$fh = "SOME_FH" ; # strict-refs hostiles ; même paquet seulement
$fh = *CERTAINS_FH; # typeglob
$fh = \*SOME_FH; # ref to typeglob (béniable)
$fh = *SOME_FH{IO} ; # Béni IO::Handle de *SOME_FH typeglob

Ou, vous pouvez utiliser la méthode "new" de l'un des modules IO::* pour créer un fichier anonyme
gestionnaire de fichier et stockez-le dans une variable scalaire.

utiliser IO::Handle; # 5.004 ou supérieur
mon $fh = IO::Handle->new();

Ensuite, utilisez l'un de ceux-ci comme vous le feriez avec un descripteur de fichier normal. Partout où Perl attend un
filehandle, un descripteur de fichier indirect peut être utilisé à la place. Un descripteur de fichier indirect n'est qu'un
variable scalaire qui contient un descripteur de fichier. Des fonctions comme « imprimer », « ouvrir », « rechercher » ou le
" " L'opérateur diamant acceptera soit un descripteur de fichier nommé, soit une variable scalaire
contenant un :

($ifh, $ofh, $efh) = (*STDIN, *STDOUT, *STDERR);
print $ofh "Tapez-le : " ;
mon $got = <$ifh>
print $efh "Qu'est-ce que c'était : $got" ;

Si vous passez un descripteur de fichier à une fonction, vous pouvez écrire la fonction de deux manières :

sous accept_fh {
mon $fh = décalage ;
print $fh "Envoi vers le descripteur de fichier indirect\n" ;
}

Ou il peut localiser un typeglob et utiliser directement le descripteur de fichier :

sous accept_fh {
local *FH = décalage ;
print FH "Envoi vers le descripteur de fichier localisé\n" ;
}

Les deux styles fonctionnent avec des objets ou des typesglobs de vrais descripteurs de fichiers. (Ils peuvent aussi
travailler avec des chaînes dans certaines circonstances, mais c'est risqué.)

accept_fh(*STDOUT);
accept_fh($poignée);

Dans les exemples ci-dessus, nous avons affecté le descripteur de fichier à une variable scalaire avant de l'utiliser.
En effet, seules des variables scalaires simples, et non des expressions ou des indices de hachage ou
tableaux, peut être utilisé avec des éléments intégrés tels que "print", "printf" ou l'opérateur diamond. À l'aide de
autre chose qu'une simple variable scalaire en tant que descripteur de fichier est illégal et ne le fera même pas
compiler:

mon @fd = (*STDIN, *STDOUT, *STDERR);
print $fd[1] "Tapez-le : " ; # TORT
mon $got = <$fd[0]> # FAUX
print $fd[2] "Qu'est-ce que c'était : $got" ; # TORT

Avec "print" et "printf", vous contournez cela en utilisant un bloc et une expression où
vous placeriez le descripteur de fichier :

print { $fd[1] } "trucs amusants\n" ;
printf { $fd[1] } "Patient les pauvres %x.\n", 3_735_928_559;
# Pitié pour le pauvre boeuf mort.

Ce bloc est un bloc approprié comme un autre, vous pouvez donc y mettre du code plus compliqué.
Cela envoie le message à l'un des deux endroits suivants :

mon $ok = -x "/bin/chat";
print { $ok ? $fd[1] : $fd[2] } "cat stat $ok\n" ;
print { $fd[ 1+ ($ok || 0) ] } "cat stat $ok\n" ;

Cette approche consistant à traiter "print" et "printf" comme des appels de méthodes objet ne fonctionne pas pour
l'opérateur diamantaire. C'est parce que c'est un véritable opérateur, pas seulement une fonction avec un
argument sans virgule. En supposant que vous ayez stocké des typesglobs dans votre structure comme nous l'avons fait
ci-dessus, vous pouvez utiliser la fonction intégrée nommée "readline" pour lire un enregistrement tout comme "<>"
Est-ce que. Compte tenu de l'initialisation indiquée ci-dessus pour @fd, cela fonctionnerait, mais uniquement parce que
lire la ligne() nécessite un typeglob. Cela ne fonctionne pas avec les objets ou les chaînes, ce qui peut être un
bug que nous n'avons pas encore corrigé.

$got = readline($fd[0]);

Notons que l'écaillement des descripteurs de fichiers indirects n'est pas lié au fait que
ce sont des chaînes, des typesglobs, des objets ou n'importe quoi d'autre. C'est la syntaxe du fondamental
les opérateurs. Jouer au jeu d'objets ne vous aide pas du tout ici.

Comment la Vous pouvez I set up a pied de page le format à be d'utiliser avec écrire ()?
Il n'y a pas de moyen intégré de le faire, mais perlform a quelques techniques pour le faire
possible pour le hacker intrépide.

Comment la Vous pouvez I écrire () développement a chaîne?
(contribution de brian d foy)

Si vous voulez "écrire" dans une chaîne, il vous suffit de un descripteur de fichier à une chaîne,
ce que Perl est capable de faire depuis Perl 5.6 :

ouvrir FH, '>', \my $string;
écrire( FH );

Puisque vous voulez être un bon programmeur, vous voudrez probablement utiliser un descripteur de fichier lexical,
même si les formats sont conçus pour fonctionner avec des descripteurs de mots nus puisque la valeur par défaut
les noms de format prennent le nom du descripteur de fichier. Cependant, vous pouvez contrôler cela avec du Perl
variables spéciales par descripteur de fichier : $^, qui nomme le format de haut de page, et $~ qui
montre le format de la ligne. Vous devez modifier le descripteur de fichier par défaut pour définir ces variables :

open my($fh), '>', \my $string;

{ # définit les variables par descripteur de fichier
mon $old_fh = select( $fh );
$~ = 'ANIMAL';
$^ = 'ANIMAL_TOP';
sélectionner( $old_fh );
}

format ANIMAL_TOP =
Nom du type d'identifiant
.

format ANIMAUX =
@## @<<< @<<<<<<<<<<<<<
$id, $type, $nom
.

Bien que l'écriture puisse fonctionner avec des variables lexicales ou de package, quelles que soient les variables que vous utilisez
à portée dans le format. Cela signifie très probablement que vous voudrez localiser un paquet
variables:

{
local( $id, $type, $name ) = qw( 12 cat Buster );
écrire( $fh );
}

imprimer $chaîne ;

Il y a aussi quelques astuces que vous pouvez jouer avec "formline" et la variable d'accumulateur
$^A, mais vous perdez une grande partie de la valeur des formats car "formline" ne gère pas la pagination et
bientôt. Vous finissez par réimplémenter les formats lorsque vous les utilisez.

Comment la Vous pouvez I ouvert a descripteur de fichier à a chaîne?
(contribution de Peter J. Holzer, [email protected])

Depuis Perl 5.8.0, un descripteur de fichier faisant référence à une chaîne peut être créé en appelant open avec un
référence à cette chaîne au lieu du nom de fichier. Ce descripteur de fichier peut ensuite être utilisé pour
lire ou écrire dans la chaîne :

open(my $fh, '>', \$string) ou die "Impossible d'ouvrir la chaîne pour l'écriture" ;
print $fh "foo\n" ;
print $fh "bar\n" ; # $string contient maintenant "foo\nbar\n"

open(my $fh, '<', \$string) ou die "Impossible d'ouvrir la chaîne pour la lecture" ;
mon $x = <$fh> ; # $x contient maintenant "foo\n"

Avec les anciennes versions de Perl, le module IO::String offre des fonctionnalités similaires.

Comment la Vous pouvez I sortie my numéros avec virgules ajoutée?
(contribué par brian d foy et Benjamin Goldberg)

Vous pouvez utiliser Number::Format pour séparer les emplacements dans un nombre. Il gère les informations locales
pour ceux d'entre vous qui veulent insérer des points à la place (ou toute autre chose qu'ils veulent
utiliser, vraiment).

Ce sous-programme ajoutera des virgules à votre numéro :

sous-commettre {
local $_ = décalage ;
1 tandis que s/^([-+]?\d+)(\d{3})/$1,$2/;
renvoie $_ ;
}

Cette regex de Benjamin Goldberg ajoutera des virgules aux nombres :

s/(^[-+]?\d+?(?=(?>(?:\d{3})+)(?!\d))|\G\d{3}(?=\d) )/1 $/g ;

C'est plus facile à voir avec les commentaires :

s/(
^[-+] ? # début du numéro.
\d+ ? # premiers chiffres avant la première virgule
(?= # suivi de, (mais non inclus dans le match) :
(?>(?:\d{3})+) # un multiple positif de trois chiffres.
(?!\d) # un multiple *exact*, pas x * 3 + 1 ou autre.
)
| # ou:
\G\d{3} # après le dernier groupe, obtient trois chiffres
(?=\d) # mais ils doivent avoir plus de chiffres après eux.
)/1 $/xg ;

Comment la Vous pouvez I traduire tilde (~) in a nom de fichier?
Utilisez l'opérateur <> ("glob()"), documenté dans perlfunc. Versions de Perl antérieures à la 5.6
nécessite que vous ayez un shell installé qui groks tildes. Les versions ultérieures de Perl ont
cette fonctionnalité intégrée. Le module File::KGlob (disponible à partir de CPAN) donne plus de portable
fonctionnalité globale.

Dans Perl, vous pouvez utiliser ceci directement :

$nom_fichier =~ s{
^ ~ # trouver un tilde de tête
( # enregistrez ceci dans $1
[^/] # un caractère non-slash
* # répété 0 fois ou plus (0 signifie moi)
)
}{
$1
? (getpwnam($1))[7]
: ( $ENV{HOME} || $ENV{LOGDIR} )
}ex;

Comment la comment quand I ouvert a filet lire écrire it lingettes it en dehors?
Parce que vous utilisez quelque chose comme ça, qui tronque le fichier puis vous donne la lecture-
accès en écriture :

ouvrir mon $fh, '+>', '/chemin/nom' ; # FAUX (presque toujours)

Oups. Vous devriez plutôt utiliser ceci, qui échouera si le fichier n'existe pas :

ouvrir mon $fh, '+<', '/chemin/nom'; # ouvert pour mise à jour

L'utilisation de ">" écrase ou crée toujours. L'utilisation de "<" ne le fait jamais non plus. Le "+" ne change pas
ce.

Voici des exemples de nombreux types de fichiers ouverts. Ceux qui utilisent "sysopen" supposent tous que
vous avez extrait les constantes de Fcntl :

utilisez Fcntl ;

Pour ouvrir le fichier en lecture :

ouvrir mon $fh, '<', $path ou mourir $!;
sysopen my $fh, $path, O_RDONLY ou die $!;

Pour ouvrir le fichier en écriture, créez un nouveau fichier si nécessaire ou tronquez l'ancien fichier :

ouvrir mon $fh, '>', $path ou mourir $!;
sysopen my $fh, $path, O_WRONLY|O_TRUNC|O_CREAT ou die $!;
sysopen my $fh, $path, O_WRONLY|O_TRUNC|O_CREAT, 0666 ou mourir $!;

Pour ouvrir le fichier en écriture, créez un nouveau fichier, le fichier ne doit pas exister :

sysopen my $fh, $path, O_WRONLY|O_EXCL|O_CREAT ou die $!;
sysopen my $fh, $path, O_WRONLY|O_EXCL|O_CREAT, 0666 ou die $!;

Pour ouvrir le fichier à ajouter, créez si nécessaire :

ouvrir mon $fh, '>>' $path ou mourir $!;
sysopen my $fh, $path, O_WRONLY|O_APPEND|O_CREAT ou mourir $!;
sysopen my $fh, $path, O_WRONLY|O_APPEND|O_CREAT, 0666 ou mourir $!;

Pour ouvrir le fichier à ajouter, le fichier doit exister :

sysopen my $fh, $path, O_WRONLY|O_APPEND ou die $!;

Pour ouvrir le fichier à mettre à jour, le fichier doit exister :

ouvrir mon $fh, '+<', $path ou mourir $!;
sysopen my $fh, $path, O_RDWR ou die $!;

Pour ouvrir le fichier à mettre à jour, créez un fichier si nécessaire :

sysopen my $fh, $path, O_RDWR|O_CREAT ou die $!;
sysopen my $fh, $path, O_RDWR|O_CREAT, 0666 ou die $!;

Pour ouvrir le fichier pour mise à jour, le fichier ne doit pas exister :

sysopen my $fh, $path, O_RDWR|O_EXCL|O_CREAT ou die $!;
sysopen my $fh, $path, O_RDWR|O_EXCL|O_CREAT, 0666 ou die $!;

Pour ouvrir un fichier sans bloquer, en créant si nécessaire :

sysopen mon $fh, '/foo/somefile', O_WRONLY|O_NDELAY|O_CREAT
ou die "can't open /foo/somefile: $!":

Soyez averti que ni la création ni la suppression de fichiers ne sont garanties d'être un atomique
fonctionnement sur NFS. C'est-à-dire que deux processus peuvent à la fois créer ou dissocier avec succès le
même fichier ! Par conséquent, O_EXCL n'est pas aussi exclusif que vous le souhaiteriez.

Voir aussi perlopentut.

Pourquoi Choisir do I parfois obtenez an "Argument liste trop longue" quand I utilisé <*> ?
L'opérateur "<>" effectue une opération de globalisation (voir ci-dessus). Dans les versions antérieures de Perl
que v5.6.0, l'interne globe () fourches d'opérateur csh(1) pour faire l'expansion glob réelle,
mais csh ne peut pas gérer plus de 127 éléments et donne donc le message d'erreur "Liste d'arguments aussi
long". Les personnes qui ont installé tcsh en tant que csh n'auront pas ce problème, mais leurs utilisateurs peuvent être
surpris par cela.

Pour contourner ce problème, mettez à niveau vers Perl v5.6.0 ou une version ultérieure, faites le glob vous-même avec
readdir () et des modèles, ou utilisez un module comme File::Glob, un module qui n'utilise pas le shell pour
faire du globbing.

Comment la Vous pouvez I ouvert a filet avec a conduisant ">" or traînant blancs ?
(contribution de Brian McCauley)

La forme spéciale à deux arguments de Perl ouvrir() la fonction ignore les blancs de fin dans
noms de fichiers et déduit le mode de certains caractères de début (ou d'un "|") de fin. Dans
anciennes versions de Perl c'était la seule version de ouvrir() et c'est donc répandu dans l'ancien
code et livres.

À moins que vous n'ayez une raison particulière d'utiliser la forme à deux arguments, vous devriez utiliser la forme à trois
forme d'argument de ouvrir() qui ne traite aucun caractère du nom de fichier comme spécial.

ouvrir mon $fh, "<", "fichier" ; # le nom du fichier est " fichier "
ouvrir mon $fh, ">", ">fichier" ; # le nom du fichier est ">fichier"

Comment la Vous pouvez I fiable rebaptiser a fichier?
Si votre système d'exploitation prend en charge un mv(1) utilitaire ou son équivalent fonctionnel,
cela marche:

rename($old, $new) ou system("mv", $old, $new);

Il peut être plus portable d'utiliser le module File::Copy à la place. Vous venez de copier vers le nouveau
vers le nouveau nom (vérification des valeurs de retour), puis supprimez l'ancien. Ce n'est pas vraiment
la même sémantiquement qu'un "rename()", qui préserve les méta-informations comme les permissions,
horodatages, informations sur les inodes, etc.

Comment la Vous pouvez I bloquer a fichier?
Perl intégré troupeau() fonction (voir perlfunc pour plus de détails) appellera troupeau(2) si cela
existe, fctl(2) si ce n'est pas le cas (sur perl version 5.004 et versions ultérieures), et verrou(3) si ni l'un ni l'autre
des deux appels système précédents existe. Sur certains systèmes, il peut même utiliser un autre
forme de verrouillage natif. Voici quelques pièges avec Perl troupeau():

1. Produit une erreur fatale si aucun des trois appels système (ou leur proche équivalent)
existe.

2. verrou(3) ne fournit pas de verrouillage partagé et requiert que le descripteur de fichier soit ouvert pendant
écriture (ou ajout, ou lecture/écriture).

3. Certaines versions de troupeau() ne peut pas verrouiller les fichiers sur un réseau (par exemple sur les systèmes de fichiers NFS),
il faudrait donc forcer l'utilisation de fctl(2) lorsque vous construisez Perl. Mais même cela est
au mieux douteux. Voir l'entrée du troupeau de perlfunc et le INSTALLER fichier dans la source
distribution pour obtenir des informations sur la création de Perl pour ce faire.

Deux sémantiques de troupeau potentiellement non évidentes mais traditionnelles sont qu'il attend
indéfiniment jusqu'à ce que le verrou soit accordé et que ses verrous soient seulement consultatif. Tel
les verrous discrétionnaires sont plus souples, mais offrent moins de garanties. Cela signifie que
fichiers verrouillés avec troupeau() peut être modifié par des programmes qui n'utilisent pas également troupeau().
Les voitures qui s'arrêtent aux feux rouges s'entendent bien, mais pas avec les voitures qui
ne vous arrêtez pas aux feux rouges. Voir la page de manuel perlport, spécifique à votre port
documentation, ou les pages de manuel locales spécifiques à votre système pour plus de détails. Il vaut mieux assumer
comportement traditionnel si vous écrivez des programmes portables. (Si vous ne l'êtes pas, vous devriez
comme toujours, n'hésitez pas à écrire pour les particularités de votre propre système (parfois
appelés « caractéristiques »). L'adhésion servile aux problèmes de portabilité ne devrait pas entrer en ligne de compte
façon de faire votre travail.)

Pour plus d'informations sur le verrouillage de fichiers, consultez également "Verrouillage de fichiers" dans perlopentut si vous
l'avoir (nouveau pour 5.6).

Pourquoi Choisir ne peut pas I juste ouvrir(FH, ">fichier.lock") ?
Un bout de code commun ne pas À UTILISATION est la suivante:

sleep(3) while -e 'fichier.lock'; # VEUILLEZ NE PAS UTILISER
ouvrir mon $lock, '>', 'file.lock'; # CE CODE CASSÉ

C'est une condition de course classique : vous faites deux pas pour faire quelque chose qui doit être fait en
une. C'est pourquoi le matériel informatique fournit une instruction de test et de configuration atomique. En théorie,
ce "devrait" fonctionner:

sysopen mon $fh, "file.lock", O_WRONLY|O_EXCL|O_CREAT
ou die "Impossible d'ouvrir file.lock: $!";

sauf que malheureusement, la création (et la suppression) de fichiers n'est pas atomique sur NFS, donc cela ne
travailler (au moins, pas à chaque fois) sur le net. Divers schémas impliquant relier() sont considérés
suggéré, mais ceux-ci ont tendance à impliquer une attente occupée, ce qui est également moins que souhaitable.

I parfois surprenante ne le font pas obtenez verrouillage. I juste souhaitez à incrément le nombre in le fichier. Comment la Vous pouvez I do ?
Personne ne vous a jamais dit que les compteurs d'accès aux pages Web étaient inutiles ? Ils ne comptent pas le nombre
de hits, ils sont une perte de temps, et ils ne servent qu'à caresser la vanité de l'écrivain. C'est
mieux choisir un nombre aléatoire; ils sont plus réalistes.

Quoi qu'il en soit, c'est ce que vous pouvez faire si vous ne pouvez pas vous en empêcher.

utilisez Fcntl qw(:DEFAULT :flock);
sysopen my $fh, "numfile", O_RDWR|O_CREAT ou die "can't open numfile: $!";
flock $fh, LOCK_EX ou die "ne peut pas flocker numfile: $!";
mon $num = <$fh> || 0 ;
chercher $fh, 0, 0 ou mourir "ne peut pas rembobiner numfile: $!";
tronquer $fh, 0 ou mourir "ne peut pas tronquer numfile: $!";
(print $fh $num+1, "\n") ou die "can't write numfile: $!";
fermez $fh ou die "ne peut pas fermer numfile: $!";

Voici un bien meilleur compteur d'accès à une page Web :

$hits = int( (temps() - 850_000_000) / rand(1_000) );

Si le nombre n'impressionne pas vos amis, alors le code pourrait le faire. :-)

Tous I souhaitez à do is ajouter a petit montant of texte à le fin of a fichier. Do I parfois surprenante avons à utilisé
verrouillage?
Si vous êtes sur un système qui implémente correctement "flock" et que vous utilisez l'exemple en ajoutant
code de "perldoc -f flock" tout ira bien même si le système d'exploitation sur lequel vous vous trouvez ne le fait pas
implémenter correctement le mode d'ajout (si un tel système existe). Donc, si vous êtes heureux de restreindre
vous-même aux systèmes d'exploitation qui implémentent "flock" (et ce n'est pas vraiment une restriction) puis
c'est ce que vous devez faire.

Si vous savez que vous n'utiliserez qu'un système qui implémente correctement l'ajout
(c'est-à-dire pas Win32), vous pouvez alors omettre la "recherche" du code de la réponse précédente.

Si vous savez que vous écrivez uniquement du code à exécuter sur un système d'exploitation et un système de fichiers qui implémente
append correctement (un système de fichiers local sur un Unix moderne par exemple), et vous gardez le
fichier en mode tamponné par bloc et vous écrivez moins d'un tampon plein de sortie entre chaque
vidage manuel de la mémoire tampon, puis chaque charge de mémoire tampon est presque garantie d'être écrite dans
la fin du fichier en un seul morceau sans se mêler à la sortie de quelqu'un d'autre.
Vous pouvez également utiliser la fonction "syswrite" qui est simplement un wrapper autour de votre système
écrire(2) appel système.

Il y a encore une petite chance théorique qu'un signal interrompe le niveau système
Opération "write()" avant la fin. Il est également possible que certains STDIO
les implémentations peuvent appeler plusieurs "write()" de niveau système même si le tampon était vide pour
début. Il peut y avoir des systèmes où cette probabilité est réduite à zéro, et c'est
pas un problème lorsque vous utilisez ":perlio" au lieu du STDIO de votre système.

Comment la do I au hasard Mise à jour a binaire fichier?
Si vous essayez simplement de patcher un binaire, dans de nombreux cas, quelque chose d'aussi simple que cela fonctionne :

perl -i -pe 's{window manager}{window mangler}g' /usr/bin/emacs

Cependant, si vous avez des enregistrements de taille fixe, vous pouvez faire quelque chose comme ceci :

mon $RECSIZE = 220 ; # taille de l'enregistrement, en octets
mon $recno = 37 ; # quel enregistrement mettre à jour
ouvrir mon $fh, '+<', 'quelque part' ou mourir "Impossible de mettre à jour quelque part : $!";
chercher $fh, $recno * $RECSIZE, 0 ;
lire $fh, $record, $RECSIZE == $RECSIZE ou mourir "ne peut pas lire l'enregistrement $recno: $!";
# grignoter le record
chercher $fh, -$RECSIZE, 1 ;
imprimer $fh $record ;
fermer $fh ;

Le verrouillage et la vérification des erreurs sont laissés en exercice au lecteur. Ne les oubliez pas ou
vous serez bien désolé.

Comment la do I obtenez a des dossiers horodatage in perl ?
Si vous souhaitez récupérer l'heure à laquelle le fichier a été lu, écrit pour la dernière fois ou a eu son
méta-données (propriétaire, etc.) modifiées, vous utilisez le -A, -M, ou -C opérations de test de fichier en tant que
documenté dans perlfunc. Ceux-ci récupèrent l'âge du fichier (mesuré par rapport au début-
l'heure de votre programme) en jours sous forme de nombre à virgule flottante. Certaines plates-formes peuvent ne pas avoir tous
de ces temps. Voir perlport pour plus de détails. Pour récupérer le temps "brut" en secondes depuis le
époque, vous appelleriez la fonction stat, puis utiliseriez "localtime()", "gmtime()", ou
"POSIX::strftime()" pour le convertir en une forme lisible par l'homme.

Voici un exemple:

mon $write_secs = (stat($file))[9];
printf "fichier %s mis à jour à %s\n", $fichier,
scalaire heure locale($write_secs);

Si vous préférez quelque chose de plus lisible, utilisez le module File::stat (qui fait partie du standard
distribution en version 5.004 et supérieure) :

# vérification d'erreur laissée en exercice pour le lecteur.
utiliser Fichier::stat;
utiliser Time::localtime;
my $date_string = ctime(stat($file)->mtime);
print "fichier $file mis à jour à $date_string\n" ;

Le manuel de formation POSIX ::strftime() approche a l'avantage d'être, en théorie, indépendante de la
locale actuelle. Voir perllocale pour plus de détails.

Comment la do I set a des dossiers horodatage in perl ?
Vous utilisez l' utime() fonction documentée dans "utime" dans perlfunc. A titre d'exemple, voici
un petit programme qui copie les temps de lecture et d'écriture de son premier argument à tous les
reste d'entre eux.

si (@ARGV < 2) {
die "utilisation : cptimes timestamp_file other_files ...\n" ;
}
mon $timestamp = décalage;
my($atime, $mtime) = (stat($horodatage))[8,9] ;
utime $atime, $mtime, @ARGV ;

La vérification des erreurs est, comme d'habitude, laissée en exercice au lecteur.

Le perldoc pour utime a également un exemple qui a le même effet que -nous(1) sur les fichiers
qui déjà exister.

Certains systèmes de fichiers ont une capacité limitée à stocker les heures sur un fichier à l'heure prévue.
niveau de précision. Par exemple, les systèmes de fichiers FAT et HPFS sont incapables de créer des dates sur
fichiers avec une granularité plus fine que deux secondes. Il s'agit d'une limitation des systèmes de fichiers,
pas de utime().

Comment la do I impression à plus que UN filet at une fois?
Pour connecter un descripteur de fichier à plusieurs descripteurs de sortie, vous pouvez utiliser le IO::Tee ou
Tie::FileHandle::Modules multiplex.

Si vous ne devez le faire qu'une seule fois, vous pouvez imprimer individuellement sur chaque descripteur de fichier.

pour mon $fh ($fh1, $fh2, $fh3) { print $fh "whatever\n" }

Comment la Vous pouvez I lire in an tout filet tous at une fois?
L'approche Perl habituelle pour traiter toutes les lignes d'un fichier est de le faire une ligne à
un temps :

ouvrir mon $input, '<', $file ou mourir "can't open $file: $!";
while (<$input>) {
mâcher;
# faire quelque chose avec $_
}
close $input or die "ne peut pas fermer $file : $!";

C'est énormément plus efficace que de lire le fichier entier en mémoire sous forme de tableau
de lignes, puis le traiter un élément à la fois, ce qui est souvent - sinon presque
toujours - la mauvaise approche. Chaque fois que vous voyez quelqu'un faire ceci :

mes @lignes = ;

Vous devriez réfléchir longuement et sérieusement aux raisons pour lesquelles vous avez besoin de tout charger en même temps. Ce n'est juste pas
une solution évolutive.

Si vous « mmapez » le fichier avec le module File::Map de CPAN, vous pouvez virtuellement charger le
fichier entier dans une chaîne sans le stocker réellement en mémoire :

utiliser Fichier::Carte qw(fichier_map);

map_file ma $string, $filename ;

Une fois mappé, vous pouvez traiter $string comme vous le feriez pour n'importe quelle autre chaîne. Puisque vous ne
devez nécessairement charger les données, le mmap-ing peut être très rapide et peut ne pas augmenter votre
empreinte mémoire.

Vous pourriez également trouver plus amusant d'utiliser le module standard Tie::File ou le DB_File
les liaisons $DB_RECNO du module, qui vous permettent de lier un tableau à un fichier afin que l'accès
un élément du tableau accède en fait à la ligne correspondante dans le fichier.

Si vous souhaitez charger l'intégralité du fichier, vous pouvez utiliser le module Path :: Tiny pour le faire en un seul
étape simple et efficace :

utilisez Chemin::Petit;

my $all_of_it = path($filename)->slurp; # fichier entier en scalaire
my @all_lines = path($filename)->lines; # une ligne par élément

Ou vous pouvez lire l'intégralité du contenu du fichier dans un scalaire comme celui-ci :

mon $var ;
{
$/ locale ;
ouvrir mon $fh, '<', $file ou mourir "can't open $file: $!";
$var = <$fh> ;
}

Cela annule temporairement la définition de votre séparateur d'enregistrements et fermera automatiquement le fichier à
sortie de bloc. Si le fichier est déjà ouvert, utilisez simplement ceci :

my $var = do { local $/; <$fh> } ;

Vous pouvez également utiliser un @ARGV localisé pour éliminer les "ouverts":

my $var = do { local( @ARGV, $/ ) = $file; <> } ;

Pour les fichiers ordinaires, vous pouvez également utiliser la fonction "lire".

lire( $fh, $var, -s $fh );

Ce troisième argument teste la taille en octets des données sur le descripteur de fichier $fh et lit que
plusieurs octets dans le tampon $var.

Comment la Vous pouvez I lire in a filet by paragraphes ?
Utilisez la variable $/ (voir perlvar pour plus de détails). Vous pouvez soit le régler sur "" pour éliminer
les paragraphes vides ("abc\n\n\n\ndef", par exemple, sont traités comme deux paragraphes et non
trois), ou "\n\n" pour accepter les paragraphes vides.

Notez qu'une ligne vierge ne doit pas contenir de blancs. Ainsi "fred\n \nstuff\n\n" est un
paragraphe, mais "fred\n\ntruc\n\n" vaut deux.

Comment la Vous pouvez I lire a unique caractère grâce au a fichier? Dès le clavier?
Vous pouvez utiliser la fonction intégrée "getc()" pour la plupart des descripteurs de fichiers, mais cela ne fonctionnera pas (facilement)
sur un terminal. Pour STDIN, utilisez le module Term::ReadKey de CPAN ou utilisez le
exemple de code dans "getc" dans perlfunc.

Si votre système prend en charge l'interface de programmation du système d'exploitation portable (POSIX), vous
pouvez utiliser le code suivant, dont vous remarquerez qu'il désactive également le traitement de l'écho.

#!/usr/bin/perl -w
utiliser strict;
$| = 1 ;
pour (1..4) {
print « donne-moi : » ;
mon $got = getone();
print "--> $got\n" ;
}
Sortie;

COMMENCER {
utiliser POSIX qw(:termios_h);

mon ($term, $oterm, $echo, $noecho, $fd_stdin);

mon $fd_stdin = fileno(STDIN);

$term = POSIX::Termios->new();
$term->getattr($fd_stdin);
$oterm = $term->getlflag();

$écho = ÉCHO | ÉCHOK | ICANON ;
$noecho = $oterm & ~$echo;

sous cbreak {
$term->setlflag($noecho);
$term->setcc(VTIME, 1);
$term->setattr($fd_stdin, TCSANOW);
}

sous-cuit {
$term->setlflag($oterm);
$term->setcc(VTIME, 0);
$term->setattr($fd_stdin, TCSANOW);
}

sous-getone {
ma clé $ = '';
cbreak();
sysread(STDIN, $clé, 1);
cuit();
renvoie $key ;
}
}

FIN { cuit() }

Le module Term::ReadKey de CPAN peut être plus facile à utiliser. Les versions récentes incluent également
la prise en charge des systèmes non portables également.

utilisez Term::ReadKey;
ouvrir mon $tty, '<', '/dev/tty';
print "Donnez-moi un caractère : " ;
ReadMode "brut" ;
ma $key = ReadKey 0, $tty;
ReadMode "normal" ;
printf "\nVous avez dit %s, numéro de caractère %03d\n",
$key, ou $key ;

Comment la Vous pouvez I dire que il y a a caractère attente on a descripteur de fichier ?
La toute première chose que vous devriez faire est de chercher à obtenir l'extension Term::ReadKey à partir de
CPAN. Comme nous l'avons mentionné plus tôt, il a même maintenant un support limité pour les non-portables (lire: pas
systèmes ouverts, systèmes fermés, propriétaires, pas POSIX, pas Unix, etc.).

Vous devriez également consulter la liste des questions fréquemment posées dans comp.unix.* pour les choses
comme ceci : la réponse est essentiellement la même. C'est très dépendant du système. en voici un
solution qui fonctionne sur les systèmes BSD :

sous-clé_prêt {
mon($rin, $nfd);
vec($rin, fileno(STDIN), 1) = 1;
return $nfd = select($rin,undef,undef,0) ;
}

Si vous voulez savoir combien de personnages vous attendent, il y a aussi l'ioctl FIONREAD
appel pour être regardé. Les h2ph l'outil fourni avec Perl essaie de convertir les fichiers d'inclusion C
au code Perl, qui peut être "requis". FIONREAD finit par être défini comme une fonction dans le
sys/ioctl.ph fichier:

requiert « sys/ioctl.ph » ;

$taille = pack("L", 0);
ioctl(FH, FIONREAD(), $size) ou die "Impossible d'appeler ioctl : $!\n" ;
$taille = unpack("L", $taille);

If h2ph n'a pas été installé ou ne fonctionne pas pour vous, vous pouvez grep les fichiers d'inclusion à la main :

% grep FIONREAD /usr/inclure/* / *
/usr/include/asm/ioctls.h:#define FIONREAD 0x541B

Ou écrivez un petit programme C à l'aide de l'éditeur de champions :

% chat > ​​fionread.c
#comprendre
principale() {
printf("%#08x\n", FIONREAD);
}
^D
% cc -o fionread fionread.c
% ./fionlecture
0x4004667f

Et puis codez-le en dur, laissant le portage comme exercice à votre successeur.

$FIONREAD = 0x4004667f; # XXX : dépendant d'opsys

$taille = pack("L", 0);
ioctl(FH, $FIONREAD, $size) ou die "Impossible d'appeler ioctl : $!\n" ;
$taille = unpack("L", $taille);

FIONREAD nécessite un descripteur de fichier connecté à un flux, ce qui signifie que sockets, pipes et tty
les appareils fonctionnent, mais pas fichiers.

Comment la do I do a "queue -F" in perl ?
Premier essai

chercher($gw_fh, 0, 1);

L'instruction "seek($gw_fh, 0, 1)" ne change pas la position actuelle, mais elle efface
la condition de fin de fichier sur le handle, de sorte que le prochain "<$gw_fh>" oblige Perl à réessayer
lire quelque chose.

Si cela ne fonctionne pas (cela dépend des fonctionnalités de votre implémentation stdio), alors vous avez besoin
quelque chose comme ça :

pour (;;) {
pour ($curpos = tell($gw_fh); <$gw_fh>; $curpos =tell($gw_fh)) {
# rechercher des trucs et les mettre dans des fichiers
}
# dormir un moment
chercher($gw_fh, $curpos, 0); # chercher où nous étions
}

Si cela ne fonctionne toujours pas, examinez la méthode "clearerr" de IO::Handle, qui réinitialise
les états d'erreur et de fin de fichier sur le handle.

Il existe également un module File::Tail de CPAN.

Comment la do I dup() a descripteur de fichier in Perl?
Si vous cochez "ouvrir" dans perlfunc, vous verrez que plusieurs des façons d'appeler ouvrir() devrait
faire l'affaire. Par exemple:

ouvrir mon $log, '>>', '/foo/logfile' ;
ouvrir STDERR, '>&', $log ;

Ou même avec un descripteur numérique littéral :

mon $fd = $ENV{MHCONTEXTFD} ;
ouvrez $mhcontext, "<&=$fd" ; # Comme fdopen(3S)

Notez que "<&STDIN" fait une copie, mais "<&=STDIN" fait un alias. Cela signifie que si vous fermez
un pseudonyme, tous les alias deviennent inaccessibles. Ce n'est pas vrai avec une copie.

La vérification des erreurs, comme toujours, a été laissée en exercice au lecteur.

Comment la do I close a filet descripteur by nombre?
Si, pour une raison quelconque, vous avez un descripteur de fichier au lieu d'un descripteur de fichier (vous avez peut-être utilisé
"POSIX::open"), vous pouvez utiliser la fonction "close()" du module POSIX :

utilisez POSIX ();

POSIX::close( $fd );

Cela devrait rarement être nécessaire, car la fonction Perl "close()" doit être utilisée pour des choses
que Perl s'est ouvert, même s'il s'agissait d'une copie d'un descripteur numérique comme avec "MHCONTEXT"
dessus. Mais si vous le devez vraiment, vous pourrez peut-être le faire :

nécessite 'sys/syscall.ph' ;
mon $rc = syscall(SYS_close(), $fd + 0); # doit forcer le numérique
die "ne peut pas sysclose $fd: $!" à moins que $rc == -1;

Ou, utilisez simplement le fdopen(3S) fonctionnalité de "open()":

{
ouvrir mon $fh, "<&=$fd" ou mourir "Impossible de rouvrir fd=$fd: $!";
fermer $fh ;
}

Pourquoi Choisir ne peut pas I utilisé "C:\temp\foo" in DOS chemins ? Pourquoi Choisir ne pas `C:\temp\foo.exe` marche ?
Oups ! Vous venez de mettre un onglet et un flux de formulaire dans ce nom de fichier ! Rappelez-vous qu'à l'intérieur
chaînes entre guillemets ("like\this"), la barre oblique inverse est un caractère d'échappement. La liste complète
de ceux-ci se trouve dans "Devis et opérateurs de type devis" dans perlop. Sans surprise, vous n'avez pas
un fichier appelé "c:(tab)emp(formfeed)oo" ou "c:(tab)emp(formfeed)oo.exe" sur votre ancien DOS
système de fichiers.

Soit entre guillemets simples vos chaînes, soit (de préférence) utilisez des barres obliques. Étant donné que tous les DOS et
Les versions Windows depuis quelque chose comme MS-DOS 2.0 ont traité "/" et "\" de la même manière
dans un chemin, vous pouvez aussi bien utiliser celui qui n'entre pas en conflit avec Perl - ou le shell POSIX,
ANSI C et C++, awk, Tcl, Java ou Python, pour n'en citer que quelques-uns. Les chemins POSIX sont plus
portable aussi.

Pourquoi Choisir ne pas glob("*.*") obtenez tous le fichiers?
Parce que même sur les ports non Unix, la fonction glob de Perl suit le glob standard Unix
sémantique. Vous aurez besoin de "glob("*")" pour obtenir tous les fichiers (non cachés). Cela fait globe ()
portable même vers les systèmes hérités. Votre port peut inclure des fonctions de globalisation propriétaires telles que
bien. Consultez sa documentation pour plus de détails.

Pourquoi Choisir ne Perl laisser me delete en lecture seule fichiers? Pourquoi Choisir ne "-JE" tabasser protégé fichiers? N'est pas ceci.
a bug in Perl?
Ceci est minutieusement et minutieusement décrit dans le fichier-dir-perms article dans le "Loin
Collection "Plus que vous n'avez jamais voulu savoir" dans
<http://www.cpan.org/misc/olddoc/FMTEYEWTK.tgz>.

Le résumé : découvrez comment fonctionne votre système de fichiers. Les permissions sur un fichier disent quoi
peut arriver aux données de ce fichier. Les permissions sur un répertoire disent ce qui peut arriver
à la liste des fichiers de ce répertoire. Si vous supprimez un fichier, vous supprimez son nom
du répertoire (donc l'opération dépend des permissions du répertoire, pas de
le fichier). Si vous essayez d'écrire dans le fichier, les autorisations du fichier déterminent si
vous y êtes autorisé.

Comment la do I Sélectionner a aléatoire en ligne grâce au a fichier?
A moins de charger le fichier dans une base de données ou de pré-indexer les lignes du fichier, il existe
quelques choses que vous pouvez faire.

Voici un algorithme d'échantillonnage de réservoir du Camel Book :

sable;
rand($.) < 1 && ($line = $_) while <>;

Cela présente un avantage significatif en termes d'espace par rapport à la lecture de l'intégralité du fichier. Vous pouvez trouver un
preuve de cette méthode dans Le manuel de formation Art of Ordinateur Programmation, Volume 2, Section 3.4.2, par
Donald E. Knuth.

Vous pouvez utiliser le module File::Random qui fournit une fonction pour cet algorithme :

utilisez File::Random qw/random_line/;
ma $line = random_line($filename);

Une autre façon est d'utiliser le module Tie::File, qui traite le fichier entier comme un tableau.
Accédez simplement à un élément de tableau aléatoire.

Pourquoi Choisir do I obtenez bizarre surpeuplés quand I impression an tableau of lignes?
(contribution de brian d foy)

Si vous voyez des espaces entre les éléments de votre tableau lorsque vous imprimez le tableau, vous
interpolent probablement le tableau entre guillemets :

mes @animaux = qw(camel lama alpaga vigogne);
print "les animaux sont : @animaux\n" ;

Ce sont les guillemets doubles, pas le "print", qui font cela. Chaque fois que vous interpolez un tableau dans
un contexte de guillemets doubles, Perl joint les éléments avec des espaces (ou tout ce qui est dans $", qui
est un espace par défaut):

les animaux sont : chameau lama alpaga vigogne

C'est différent de l'impression du tableau sans interpolation :

mes @animaux = qw(camel lama alpaga vigogne);
print "les animaux sont : ", @animaux, "\n" ;

Maintenant, la sortie n'a pas les espaces entre les éléments parce que les éléments de
@animals devient simplement une partie de la liste à "imprimer":

les animaux sont : camelllamaalpacavicuna

Vous remarquerez peut-être cela lorsque chacun des éléments de @array se termine par une nouvelle ligne. Vous vous attendez
pour imprimer un élément par ligne, mais notez que chaque ligne après la première est en retrait :

c'est une ligne
c'est une autre ligne
c'est la troisième ligne

Cet espace supplémentaire provient de l'interpolation du tableau. Si vous ne voulez pas mettre
quoi que ce soit entre les éléments de votre tableau, n'utilisez pas le tableau entre guillemets doubles. Vous pouvez envoyer
à imprimer sans eux :

imprimer @lignes ;

Comment la do I traverser a annuaire arbre?
(contribution de brian d foy)

Le module File::Find, fourni avec Perl, fait tout le travail difficile pour parcourir un
structure de répertoire. Il est livré avec Perl. Vous appelez simplement le sous-programme "trouver" avec un
sous-programme de rappel et les répertoires que vous souhaitez parcourir :

utiliser Fichier::Rechercher ;

find( \&voulait, @répertoires );

sous voulait {
# chemin complet dans $File::Find::name
# juste le nom du fichier dans $_
... faites ce que vous voulez faire ...
}

Le File::Find::Closures, que vous pouvez télécharger à partir du CPAN, fournit de nombreux fichiers prêts à l'emploi
sous-routines que vous pouvez utiliser avec File::Find.

Le File::Finder, que vous pouvez télécharger depuis CPAN, peut vous aider à créer le rappel
sous-routine en utilisant quelque chose de plus proche de la syntaxe de l'utilitaire de ligne de commande "find":

utiliser Fichier::Rechercher ;
utilisez File::Finder;

my $deep_dirs = File::Finder->depth->type('d')->ls->exec('rmdir','{}');

find( $deep_dirs->as_options, @places );

Le module File::Find::Rule, que vous pouvez télécharger depuis CPAN, a une interface similaire,
mais fait la traversée pour vous aussi :

utiliser File::Find::Rule;

my @files = File::Find::Rule->file()
->nom( '*.pm' )
->in( @INC );

Comment la do I delete a annuaire arbre?
(contribution de brian d foy)

Si vous avez un répertoire vide, vous pouvez utiliser le "rmdir" intégré à Perl. Si le répertoire est
pas vide (donc pas de fichiers ou de sous-répertoires), soit vous devez le vider vous-même (beaucoup de
travail) ou utilisez un module pour vous aider.

Le module File::Path, fourni avec Perl, a un "remove_tree" qui peut s'occuper de
tout le travail acharné pour vous:

utilisez File::Path qw(remove_tree);

remove_tree( @répertoires );

Le module File::Path possède également une interface héritée avec l'ancien sous-programme "rmtree".

Comment la do I copier an tout annuaire?
(contribué par Shlomi Fish)

Pour faire l'équivalent de "cp -R" (c'est-à-dire copier une arborescence de répertoires entière de manière récursive) dans
Perl portable, vous devrez soit écrire quelque chose vous-même, soit trouver un bon module CPAN
tels que File::Copy::Recursive.

AUTEUR ET DROIT D'AUTEUR


Copyright (c) 1997-2010 Tom Christiansen, Nathan Torkington et autres auteurs, comme indiqué.
Tous droits réservés.

Cette documentation est gratuite ; vous pouvez le redistribuer et/ou le modifier dans les mêmes conditions
comme Perl lui-même.

Indépendamment de sa distribution, tous les exemples de code ici sont dans le domaine public. Tu es
autorisé et encouragé à utiliser ce code et tous ses dérivés dans vos propres programmes
pour le plaisir ou pour le profit comme bon vous semble. Un simple commentaire dans le code donnant crédit au
La FAQ serait courtoise mais n'est pas obligatoire.

Utilisez perlfaq5 en ligne en utilisant les services onworks.net


Serveurs et postes de travail gratuits

Télécharger des applications Windows et Linux

Commandes Linux

Ad




×
Publicité
❤ ️Achetez, réservez ou achetez ici — gratuitement, contribue à maintenir la gratuité des services.