Article publié dans Linux Magazine 100, décembre 2007.
Pour fêter le numéro 100 de votre magazine, les Mongueurs de Perl vous offrent 100 unilignes Perl, du plus trivial au plus puissant, en passant par le plus golfé.
Le but de cette liste n'est pas de s'amuser à réécrire certains outils Unix en Perl : Perl est disponible sur de nombreuses plate-formes qui ne disposent pas de tels outils, et certains de ces unilignes permettent d'importer sur une plate-forme un peu limitée un peu de la puissance d'Unix.
Merci à
Christian Aperghis-Tramoni,
Sébastien Aperghis-Tramoni,
Sofian Brabez,
Philippe Bruhat,
Dominique Dumont,
Dominique Pasquier,
Jean Forget,
Laurent Gautrot,
Julien Gilles,
Patrice Guerlais,
Lars Nef,
David Rigaudiere,
Michel Rodriguez,
et
Julien Tayon
pour leurs contributions, et à toute la liste perl@mongueurs.net
pour les discussions autour de cette liste d'unilignes.
perl -v
Affiche la version de Perl et la licence.
perl -le 'print $]'
Affiche la version de Perl (5.008008
).
perl -V
Affiche un sommaire des principales options de configuration de Perl,
et le contenu de @INC
.
perl -V:clé
Affiche la valeur de la clé correspondante de %Config
. La clé peut
être une expression régulière, affichant alors toutes les clés et valeurs
correspondantes.
perl -V::clé
Comme précédemment, mais sans affichage du nom des clés.
perl -le 'print for@INC'
Affiche les répertoires du chemin d'inclusion des librairies de Perl.
perl -lneprint+eval
"Shell" Perl de type REPL (Read Eval Print Loop). Très pratique pour effectuer une série de calculs par exemple.
perl -de0
En partie similaire au précédent, mais cette fois-ci dans le debogueur Perl.
perl -Mmodule -e1
Permet de savoir rapidement si un module est installé. S'il ne l'est pas,
Perl explose en vol avec le message Can't locate modulein @INC
.
perl -Mmodule\ 999
Permet de connaître la version d'un module installé. Le message d'erreur indique la version installée. Il faut protéger l'espace par un antislash (ou mettre l'option, le nom du module et le nombre entre quotes) pour des raisons liées à la manière dont Perl analyse les arguments passés aux modules.
perl -MV=module
Affiche le chemin et la version de tous les fichiers correspondants au
nom de module indiqué. Il faut manuellement installer le module V
,
disponible à http://www.test-smoke.org/download/V-0.11.tar.gz
(http://xrl.us/3kpf).
perl -MCPAN -e shell
Shell d'installation de modules CPAN si la commande cpan(1)
n'est pas
disponible.
perl -MCPAN -e install+Mon::Module
Installation rapide d'un module, en s'épargnant l'utilisation de guillemets. Cette installation est d'autant plus rapide qu'on a un mini-CPAN en local.
perl -pi -e's/\015\012/\012/g'
fichier_dos.txt
Un dos2unix
portable. Permet de convertir les retours chariots vers le
format unix. Pratique après un transfert FTP effectué en mode binaire au
lieu de ASCII.
perl -w015l12pi -e1
fichier_mac.txt
Un mac2unix
portable,
qui a obtenu la deuxième place de la catégorie
du programme le plus puissant de l'OPC-0
(Obfuscated Perl Contest, concours de Perl assombri), en 1996.
perl -lne '$o=$_;s/motif/remplacement/;rename$o,$_'
Un système de renommage surpuissant. Le nom du fichier est reconnu et
transformé dans le s///
à coups de regexps. C'est un filtre car j'ai
l'habitude de l'utiliser en lui passant une liste de fichiers par ls
avec ls -1 *.log | uniligne
.
Voir aussi la fonction rename()
fournie avec Perl.
perl -eunlink,for@ARGV> fichier ...
Quand rm(1)
vous trahit, par exemple si un fichier commence par un tiret.
perl -eunlink+glob+shift> "glob" ...
Cette variante peut s'avérer utile si le shell refuse d'exécuter une commande parce que la liste d'arguments est trop longue.
perl -pi -e 's/motif/remplacement/g' fichier ...
Rechercher-remplacer en masse (et sans backup).
perl -e '/(.+)\.bak$/&&rename$_,$1 for@ARGV' *.bak
Si on a fait une sauvegarde (par exemple avec -i.bak) avec son uniligne à base de -p ou -l, il est possible de faire un retour arrière avec celui-ci.
perl -lane 'print $F[0]+$F[-2]'
fichier
Calcule la somme du premier et du pénultième champ de chaque ligne.
Active le mode awk
: @F
est renseigné par l'option -a, et on peut changer l'expression pour la découpe des champs avec l'option -F.
perl -n000e 'print if /regexp/'
fichier
Affiche l'ensemble des paragraphes qui contiennent l'expression regexp
.
Pratique pour une recherche dans un fichier texte, pour avoir un peu
de contexte.
perl -ne 'print if/regexp de debut/../regexp de fin/'
fichier
Affiche uniquement les extraits du fichier contenus entre une ligne
qui correspond à la /regexp de debut/
et une ligne qui correspond
à la /regexp de fin/
.
perl -ne 'print if /regexp de debut/.../regexp de fin/'
fichier
Même chose que précédemment, sauf que si la même ligne correspond aux
deux expressions régulières, l'affichage continuera jusqu'à la prochaine
ligne qui correspond à /regexp de fin/
. (Consulter la page de manuel
perlop(1) à la section Range operators pour plus de détails.)
perl -ne 'print if 14 .. 42'
fichier
Imprime les lignes 14 à 42, avec l'utilisation d'un cas particulier des
opérateurs d'intervalle. Remplacer if
par unless
pour imprimer tous
le fichier sauf les lignes 14 à 42.
perl -ne 'print if ($seen{$_} .= @ARGV) =~ /10$/' fichier1 fichier2
Imprime les lignes communes aux fichiers (posté par Randal Schwartz sur PerlMonks).
perl -ne 'print if ($seen{$_} .= @ARGV) =~ /210$/' fichier1 fichier2 fichier3
Imprime les lignes communes aux fichiers. Le même, pour trois fichiers (et pour vous aider à comprendre).
perl -0nal012e '@a{@F}++; print for sort keys %a'
Extrait, trie et imprime les mots d'un fichier (par Peter J. Kernan, publié dans The Perl Journal 13).
perl -le 'for(@ARGV) {print if -f && -T _}' *
Détecte les fichiers texte (un fichier est considéré comme un fichier texte par l'opérateur -T s'il contient plus de 30% de caractères ``bizarres'' ou un caractère nul (\0) dans le premier bloc).
perl -lne 'if(length>$l){$l=length;$n=$.}}{print"$n $l"' fichier ...
Si votre éditeur ou vous-mêmes n'aimez pas les fichiers avec des lignes trop longues, cet uniligne affiche le numéro et la longueur de la ligne la plus longue du fichier.
perl -e 'print chr(32+rand 95) for 1..8'
Génère un mot de passe aléatoire.
perl -le '$i++ while getpwuid($i); print $i'
Trouve le premier UID non utilisé.
perl -MTk -e '($w=MainWindow->new)->withdraw;$w->messageBox(-title=>"Alert",-message=>"@ARGV")'
Un message à afficher
Affiche une boîte de dialogue avec le message à afficher dedans. Utile par exemple pour se définir des rappels dans un cron job, sans surcharger son agenda avec des choses mineures.
perl -MCarp=verbose programme
Transforme les appels à carp()
et croak()
de telle sorte qu'ils
affichent une stack trace.
perl -MDevel::SimpleTrace programme
Transforme tous les appels à warn()
et die()
, et par conséquent
à carp()
et croak()
, de telle sorte qu'ils affiche une stack trace.
La sortie est plus verbeuse qu'avec le précédent, mais cela peut s'avérer
très utile.
perl -ne '/regexp/&&print'
grep regexp
(avec les expressions régulières Perl).
Pour ignorer la casse (grep -i
) ajouter l'option /i en fin de
l'expression régulière (/regexp/i
).
perl -ne '/regexp/||print'
grep -v regexp
(avec les expressions régulières Perl).
Même remarque que précédemment pour l'option -i.
perl -lne '}{print$.'
wc -l
perl -MText::Autoformat -e autoformat
fmt
(en beaucoup plus puissant).
perl -pe's//$. /'
nl
perl -ne'print if!$u{$_}++'
uniq
pour n'afficher que la première occurrence d'une ligne si elle est
présente plusieurs fois dans les données (filtre ou fichier en entrée).
Il y a des variantes plus puissantes pour ne travailler que sur une colonne
comme avec perl -nae'print if!$u{$F[1]}++'
qui affiche la ligne si
la deuxième colonne n'a pas déjà été rencontrée.
Autre possibilité, travailler sur une portion de la ligne avec des regexps et
utiliser les variables $1
, $2
... pour renseigner le hash %u
. Mais
on s'éloigne beaucoup de l'uniq
classique.
perl -lne 'print for/([\w\d\P{IsCntrl}\ \t]{4,})/g'
binaire
Une commande strings utilisable quand on n'est pas sous Unix.
perl -nle 'print $& while m/[[:print:]]{4,}/g'
binaire
Une autre version de strings
.
perl -le 'print+(ord pack"s",1)?"little":"big","-endian"'
Détermine si votre machine est little-endian ou big-endian.
perl -MConfig -le 'print$Config{byteorder}'
Autre méthode, en utilisant Config.pm
. 1234
signifie little-endian
et 4321
big-endian.
perl -MMIME::Base64=decode_base64 -e 'print decode_base64 join"",<>'
Un décodeur base64
en ligne. Utile par exemple pour récupérer les mots
de passe conservés par Firefox.
perl -MMIME::Base64=encode_base64 -e 'print encode_base64 join"",<>'
Un encodeur base64
en ligne.
perl -pe 's/=(..)/chr hex $1/eg'
Un décodeur quoted-printable en ligne.
perl -pe 'tr/A-Za-z/N-ZA-Mn-za-m/'
Encodeur/décodeur ROT13.
perl -lne print+hex
Permet de convertir des nombres hexadécimaux en décimal.
Je rappelle que, de façon plutôt anti-intuitive, hex
permet de convertir à partir de l'hexadécimal, tout comme
oct
convertit à partir de l'octal.
perl -lne 'print+($_-32)*5/9'
Pour convertir des degrés Fahrenheit en Celsius.
Ou, avec d'autres formules, pour convertir n'importe
quoi en autre chose : pouces en millimètres, francs en
euros, etc. Voire pour dessiner une courbe mathématique
si vous utilisez encore le papier millimétré au lieu
de gnuplot ou assimilé. Rappelons que le signe +
entre
le print
et la parenthèse ouvrante fait que l'argument
du print
ira jusqu'au bout de la ligne et non pas
seulement jusqu'à la parenthèse fermante.
perl -Xleprint~~localtime+shift
timestamp
Affiche le groupe date/heure correspondant au timestamp de manière lisible (selon la locale courante). Le timestamp, ou nombre de secondes écoulées depuis l'epoch (http://fr.wikipedia.org/wiki/Epoch) est souvent utilisée dans des fichiers de logs.
perl -MPOSIX=strftime -le'print strftime"%Y-%m-%dT%H:%M:%S",localtime shift'
timestamp
Convertit le timestamp Epoch au format ISO 8601 (http://fr.wikipedia.org/wiki/ISO_8601).
commande | perl -pe'$_=locatime()." $_"'
Ajoute date et heure à la sortie d'une commande.
perl -MHTML::Tidy -e 'print HTML::Tidy->new->clean(<>)'
Nettoyeur HTML.
perl -MLWP::Simple -le'print$_,head$_?" OK":" KO"for@ARGV'
Teste rapidement si une liste d'URL est accessible (OK
) ou non (KO
).
perl -MHTML::Parse -MLWP::Simple -MHTML::FormatText -e 'print HTML::FormatText->new->format( parse_html get shift)'
url
url2text.
perl -l -MXML::Twig -e'print q{#1= $}, XML::Twig->parse("http://www.x-rates.com/")->first_elt(q{a[@href="/d/USD/EUR/graph120.html"]})->text'
Le cours du dollars américain, d'après le site http://www.x-rates.com/.
perl -MLWP -e '($y,$i)=shift=~/^(.+m)\/.+v=(.+)/;($m=LWP::UserAgent->new)->get("$y/get_video?video_id=$i&t=".($m->get("$y/v/$i")->request->uri=~/&t=(.+)/)[0],":content_file"=>"$i.flv")'
http://www.youtube.com/watch?v=idVideo
perl -MWWW::Mechanize -e '($y,$i)=shift=~m#(http://www\.youtube\.com)/watch\?v=(.+)#;$m=WWW::Mechanize->new;($t=$m->get("$y/v/$i")->request->uri)=~s/.*&t=(.+)/$1/;$m->get("$y/get_video?video_id=$i&t=$t",":content_file"=>"$i.flv")'
http://www.youtube.com/watch?v=idVideo
perl -MWWW::YouTube::VideoURI -MLWP::Simple -e '($u,$v)=shift=~/(^.+m\/.+v=(.+))/;getstore(WWW::YouTube::VideoURI->new()->get_video_uri($u),"$v.flv")'
http://www.youtube.com/watch?v=idVideo
Trois manières de télécharger le fichier .flv d'une vidéo sur YouTube,
avec LWP
, WWW::Mechanize
ou WWW::YouTube::VideoURI
.
perl -MSocket -ple '$_=gethostbyaddr inet_aton($_),AF_INET'
Convertit une liste d'adresse IP en Hostname.
perl -MSocket -nle 'printf"%d.%d.%d.%d\n", unpack"C4",$_ for splice @{[gethostbyname$_]},4'
Convertit une liste de nom DNS (Hostname, Alias, ...) en adresse IP.
perl -MIO::Socket -pe 'BEGIN{select IO::Socket::INET->new(PeerAddr=>shift,PeerPort =>(shift||23))}'
serveur port
Le nc
du pauvre, en client. On ne voit pas les réponses du serveur.
perl -MClass::DBI::Loader -le '@c{qw(dsn user password)}=@ARGV;$l=Class::DBI::Loader->new(%c);print"$_: @{[$_->columns]}"for$l->classes' dsn user password
Affiche les tables et les colonnes d'une base de données passée en paramètre.
perl -MTk::ObjEditor -MTie::DBI -e 'tie %h, "Tie::DBI", { db => "mysql:foodb", table => "footable", user => "foo", password => "foopw", key => "name" };Tk::ObjEditor::edit_object( \%h )'
Un éditeur de base de donnée en une ligne (ou presque). Nécessite
Tk::ObjEditor
2.006.
perl -wle 'print"Premier"if(1x shift)!~/^1?$|^(11+?)\1+$/'
nombre
Teste si un nombre est premier, par Abigail.
perl -le 'print scalar gmtime 0x7f_ff_ff_ff'
Calcule la « fin des temps » (http://fr.wikipedia.org/wiki/Bogue_de_l%27an_2038).
perl -lne 'print if $_ eq reverse'
/usr/share/dict/words
Rechercher les palindromes d'une liste (dictionnaire).
perl -le '$_=1;print&&s/((\d)\2*)/length($1).$2/ge while length()<64'
Affiche le début de la suite de Conway. http://fr.wikipedia.org/wiki/Suite_de_Conway
perl -e '$y=$_/13-1.5,print map{$a=$b=0;$c=64;$b=2*$a*$b+$y,$a=$p-$q+$_/33-1.5 while--$c&&($p=$a*$a)+($q=$b*$b)<2;$c?substr("!torblednaM",$c%11,1):" "}(0..78),"\n"for(0..38)'
Dessine un ensemble de Mandelbrot en caractères ASCII par Steven de Rooij (http://homepages.cwi.nl/~rooij/programming/oneliners.html).
Finalement, cette liste ne contient que 70 unilignes...
Nous avons préféré la qualité à la quantité en ne sélectionnant que des unilignes réellement utilisés (sauf pour la dernière partie, évidemment), et en nous arrêtant avant de proposer des exemples triviaux ou trop tarabiscotés.
À vous de compléter cette liste avec vos 30 unilignes favoris. ;-)
Envoyez vos perles à perles@mongueurs.net
, elles seront peut-être
publiées dans un prochain numéro de Linux Magazine.
Copyright © Les Mongueurs de Perl, 2001-2011
pour le site.
Les auteurs conservent le copyright de leurs articles.