Tout développeur ou ingénieur système qui a mis son nez dans du code perl connait surement déjà l’opérateur “..” ou range qui est le plus souvent utilisé pour construire une énumération.

Par exemple: my @array = (1..10); remplit @array d’un tableau comprenant tous les éléments de 1 à 10.

[vincent@Amyrlin ~ 10:46:55] perl -e 'print join(" ",(1..10)),"\n"'
1 2 3 4 5 6 7 8 9 10

Un collègue m’a faire découvrir hier une utilisation que le pense assez méconnue de cet opérateur, et que j’ai trouvée fantastique à la lecture de son code.

Effectivement, je n’avais jusqu’à présent rencontré que dans un contexte de liste, mais son utilisation en contexte scalaire est toute autre.

In scalar context, ".." returns a boolean value.  The operator is bistable,
like a flip-flop, and emulates the line-range (comma) operator of sed, awk,
and var-ious editors.  Each ".." operator maintains its own boolean state.
It is false as long as its left operand is false.  Once the left operand is
true, the range operator stays true until the right operand is true, AFTER
which the range operator becomes false again.  It doesn't become false till
the next time the range operator is evaluated.  It can test the right operand
and become false on the same evaluation it became true (as in awk), but it
still returns true once.  If you don't want it to test the right operand
till the next evaluation, as in sed, just use three dots ("...") instead
of two.  In all other regards, "..." behaves just like ".." does.

En clair cet opérateur a un état qui parmet de comparer deux conditions dans le temps.  En particulier son utilisation dans un test conditionnel a l’intérieur d’une boucle sur une liste permet de sélectionner une sous partie de cette liste. En fait comme en awk cela permet par exemple d’appliquer un bloc de code à une sous liste déterminée par 2 conditions, une condition de début et une de fin.

En pratique nous l’avons utilisée pour appliquer un bout de code à un bloc de texte dans un fichier de config. Voici un exemple concret d’utilisation. Nous avons un fichier de config sur chaque serveur qui doit contenir une partie commune à tous les serveurs délimitée par des bannières prédéfinies et une partie spécifique à chaque machine. Nous avons pu utiliser le code suivant pour scripter une modification de la partie commune:

Voici le fichier de config:

[vincent@Amyrlin ~ 11:05:20] cat toto.conf
# BEGIN UNIX TEAM
This is a common configuration par V1.
config1=a
config2=b
# END UNIX TEAM

This
	is
		a
	specific
part

Et voici le code:

[vincent@Amyrlin ~ 11:05:40] cat toto.pl
#!/usr/bin/perl -w

my $newconfig="# BEGIN UNIX TEAM
This is a common configuration par V2.
config1=a
config2=b
config3=c
# END UNIX TEAM
";
my $conf=$newconfig;

while (<>) {
	$conf .= $_ unless (/^# BEGIN UNIX TEAM/ .. /^# END UNIX TEAM/)
}
print $conf;

Exemple d’utilisation:

[vincent@Amyrlin ~ 11:06:10] ./toto.pl toto.conf
# BEGIN UNIX TEAM
This is a common configuration par V2.
config1=a
config2=b
config3=c
# END UNIX TEAM

This
	is
		a
	specific
part

C’est bien sur une utilisation simple mais on peut imaginer des chose beaucoup plus puissantes que cette simple substitution de bloc…

A vous de jouer. Et je remercie donc Pierre MACHARD pour m’avoir fait découvrir cette petite PERLe.