Sauter au contenu
17 février 2012

Comparatif grep, ack et grin

Sur le ring, grep dominait et le public l’acclamait. Mais deux petits nouveaux, ack et grin, avaient enfilé leurs plus belles tenues de super-stars du catch pour lui ravir sa ceinture de champion et le cœur des développeurs. Vont-ils y arriver ? C’est ce que vous saurez en lisant cet article !

Parfois, un programmeur veut connaître l’ensemble des occurrences d’un symbole dans un programme (une variable, une classe, etc.). La solution la plus évidente est d’utiliser grep mais, pour peu qu’il y ait d’autres fichiers dans le répertoire du projet, de nombreux faux positifs vont apparaître, rendant le travail d’analyse fastidieux. Par exemple, s’il existe des copies créées automatiquement par un éditeur de texte, les fichiers des dépôts (.svn, .hg, fichier binaire, etc.). À Yaal, nous utilisons Python. Avec virtualenv, les fichiers de dépôt, les fichiers .pyc produits automatiquement, la documentation, etc. les résultats de grep sont plus ou moins truffés de faux positifs.

Il est bien évidemment possible d’exclure ce genre de fichier en multipliant les commandes (| grep -v a_exclure). Mais l’augmentation des lignes à éliminer rend la commande toujours moins pratique. Pour contourner cela, la suite logique est de transformer la commande en un script shell. Cependant, d’autres programmes comme ack et grin visent déjà à résoudre ce problème. L’objectif de cet article est de montrer quelques spécificités de chaque outil.

Les différents outils

Voici une présentation succincte des trois adversaires :

  • grep : l’outil Unix classique qui servira de référence ;
  • ack : outil écrit en Perl visant à faire des recherches, orienté pour des développeurs. Ce logiciel est disponible dans Debian et dérivées par l’intermédiaire du paquet ack-grep. La commande est aussi ack-grep. Le changement de nom est dû au fait qu’il existait déjà un paquet du nom de ack. Dans la suite de l’article, on mentionnera simplement ack ;
  • grin : outil écrit en Python ayant le même but que ack. Il n’est pas disponible dans Debian. Étant donné qu’il est disponible dans Pypi (les dépôts de paquets Python, équivalant au CPAN de Perl), grin peut être installé avec pip install grin. Le paquet python-pip doit être préalablement installé. Puisqu’il n’y a pas de page de manuel, la documentation à utiliser est celle de grin --help et la page de documentation sur le dépôt Python.

Que le match commence !

Usage

Recherche dans un fichier

grep MOTIF FICHIER
ack-grep MOTIF FICHIER
grin MOTIF FICHIER

Dans chaque cas, MOTIF peut être une expression rationnelle (par exemple [fF]év vaut fév ou Fév).

Voici un exemple de résultats que l’on peut obtenir :

stephane@foehn:~/src/strdatetime$ grep [Ff]év translation.py
u"janv", u"févr", u"mars",
u"janvier", u"février", u"mars",
u"Janvier", u"Février", u"Mars",
stephane@foehn:~/src/strdatetime$ ack-grep [Ff]év translation.py
u"janv", u"févr", u"mars",
u"janvier", u"février", u"mars",
u"Janvier", u"Février", u"Mars",
stephane@foehn:~/src/strdatetime$ grin [Ff]év translation.py
translation.py:
   19 : u"janv", u"févr", u"mars",
   26 : u"janvier", u"février", u"mars",
   30 : u"Janvier", u"Février", u"Mars",

La sortie de grep et d’ack sont identiques, alors que grin fournit le nom du fichier et le numéro de lignes.

Recherche récursive

La plupart du temps, l’objectif est de chercher dans tout une arborescence de répertoire. C’est le fonctionnement par défaut pour ack et grin.

grep -r MOTIF . #ou rgrep
ack-grep MOTIF
grin MOTIF

La sortie produite par grep et ack évolue pour ajouter le nom du fichier et les lignes. grep met tout sur une ligne alors qu’ack a une sortie identique à celle de grin. grin produit une sortie toujours structurée de la même manière (cf. l’exemple du paragraphe précédent).

Alors que la différence de vitesse lors de l’analyse d’un seul fichier ne se sent pas, elle devient sensible lors d’une recherche récursive. Quelques tests rapides (et sans prétention d’exhaustivité ou de représentativité) donnent des résultats bien plus lents pour ack et grin.

grep : 0,3 s
ack-grep : 1,7 s
grin : 2,8 s

Cependant, ajouter des tubes pour exclure des résultats obtenus avec grep dans le but d’éliminer des résultats (et donc arriver à un résultat comparable avec ce qui est obtenu avec ack ou grin) augmentera le temps passé et donc réduira l’écart avec les deux autres outils.

Recherche insensible à la casse

grep -i MOTIF FICHIER
ack-grep -i MOTIF FICHIER
grin -i MOTIF FICHIER

Même syntaxe que dans les cas précédents, juste l’option -i en plus. Aucune surprise ici. Pas la peine d’en rajouter. Passez au paragraphe suivant. Faut-il vraiment que j’arrête d’écrire ce paragraphe pour vous arrêtiez de le lire ?!

Recherche en ignorant certains types de fichiers

Cette fonctionnalité est très utile pour ne pas chercher dans des fichiers sans intérêt :

grep -r --exclude=*.sh  --exclude=*.h "interpreted as " .
ack-grep --type=nohh --type=noshell  "interpreted as "
grin --skip-exts .h,.sh  "interpreted as "

Ici, on exclut les fichiers d’en-tête de code C (*.h) et les scripts shell (*.sh). grep et grin recherchent directement une correspondance de motif alors qu’ack permet des exclusions de types ou d’extension. Les types sont basés sur les noms d’extension de fichiers (avec la correspondance de motif). Par exemple, le type shell correspond à .sh, .bash, .csh, .tcsh, .ksh et .zsh. La définition d’un type de fichier est conçu pour être facilement extensible.

Par défaut, ack et grin exclut les répertoires et les fichiers sans intérêt. L’option d’exclusion permet d’en ajouter de nouveaux. La liste des fichiers exclus par défaut n’est pas identique entre ack et grin donc les résultats peuvent différer un peu. Par exemple, c’est le cas des fichiers .texi, exclus par ack, mais pas par grin.

Recherche en ignorant certains répertoires

grep -r --exclude-dir DIR1 --exclude-dir DIR2 MOTIF .
ack-grep --ignore-dir DIR1 --ignore-dir DIR2  MOTIF
grin --skip-dirs DIR1,DIR2 MOTIF

Ces commandes permettent d’exclure DIR1 et DIR2 de la recherche. grin ajoute les répertoires enlevés à la liste des répertoires qu’il exclut automatiquement.

Ajout des lignes de contexte

Les options sont toutes identiques et ont le même comportement.

-A, --after-context
-B, --before-context
-C, --context  #avant et après

Comme à chaque fois, grin affichage systématiquement le numéro des lignes.

Affichage limité aux fichiers correspondants

grep -r -l MOTIF.
ack-grep -l MOTIF
grin -l MOTIF

C’est donc l’option -l ou --files-with-matches à chaque fois.

Affichage limité aux fichiers non correspondants

grep -r -L MOTIF .
ack-grep -L MOTIF  # = -l -v
#rien pour grin !

L’option -L (ou --files-without-matches) permet de n’afficher que les fichiers sans l’occurence MOTIF pour grep et ack. grin a bien une option de ce nom mais son comportement est complètement différent. L’aide de la commmande signale que ce paramètre permet d’afficher le nom du fichier avec la correspondance. Ce qui est le comportement par défaut. Je ne comprend pas l’intérêt de cette option, trompeuse de surcroît.

Inversion de la sélection

grep -v MOTIF FICHIER
ack-grep -v  MOTIF FICHIER
#rien pour grin !

Pas d’option équivalente à -v pour grin. Rien ! Nada ! Zéro ! Que dalle ! ∅ !

Intégration avec un éditeur

ack dispose d’un paramètre --column pour qu’un éditeur de texte se place directement sur la première occurence.

La documentation d’ack précise que l’outil est intégrable avec Vim, Emacs et TextMate. Je n’ai testé aucune de ces possibilités.

grin dispose d’un paramètre --emacs qui affiche le nom du fichier, le numéro de la ligne et son contenu sur la même ligne pour faciliter l’analyse « par exemple avec emacs » :

stephane@foehn:~/src/strdatetime$ grin Fév
./tests.py:
  122 :         d_fr = strdatetime.strdatetime(u"Févr", "%b", lang="fr")
  136 :         d_fr = strdatetime.strdate(u"Févr", "%b", lang="fr")
./translation.py:
   30 : u"Janvier", u"Février", u"Mars",
stephane@foehn:~/src/strdatetime$ grin --emacs Fév
./tests.py:122:         d_fr = strdatetime.strdatetime(u"Févr", "%b", lang="fr")
./tests.py:136:         d_fr = strdatetime.strdate(u"Févr", "%b", lang="fr")
./translation.py:30: u"Janvier", u"Février", u"Mars",

Je suis très dubitatif sur le choix de nommage des options dans grin mais cette option me semble vraiment intéressante.

Configuration

Il est possible d’enregistrer des préférences pour qu’elles soient utilisées à chaque fois.

grep est le plus limité. Si l’utilisateur enregistre un fichier FICHIER avec tous les motifs de noms de fichier (possibilité d’utiliser les caractères jokers de l’interprète de commande) qu’il veut exclure, il peut les faire prendre en compte en utilisant --exclude-from=FICHIER. C’est limité mais cette fonctionnalité reste probablement sous-exploitée.

ack prend en compte un fichier de configuration .ackrc dans lequel on peut ajouter les options à lancer systématiquement. Simple et efficace. Certains paramètres sont aussi accessibles grâce à des variables d’environnement.

grin utilise une variable d’environnement $GRIN_ARGS. Elle doit valoir une chaîne de caractère qui inclut les paramètres à ajouter par défaut. Fonctionnel mais moins élégant que le fichier de configuration d’ack.

Conclusion

Pour une utilisation dans le cadre de développement logiciel, ack me semble le plus adapté. Par contre, le fait qu’il n’affiche pas toutes les informations sur la même ligne empêche sa sortie d’être réutilisable facilement. grin me semble moins bon mais évite cet écueil (avec --emacs) et affiche toujours les lignes, ce qui peut s’avérer assez pratique.

grep est plus généraliste et possède plus d’options. Il reste donc indispensable et a l’avantage d’être toujours disponible sur le système, ce qui n’est pas le cas des deux autres.

Je n’ai fait qu’aborder les fonctionnalités qui me semblaient les plus courantes, chacun en possède d’autres et sont à portée de man. Explorez-les !

Versions utilisées :
grep (GNU grep) 2.10
ack-grep 1.92
grin 1.2.1

17 janvier 2012

Carte heuristique de commandes unix

Voici une carte heuristique (mind map en anglais) de commandes unix.

Évidemment, la carte est loin d’être exhaustive (il n’existe pas d’écran assez grand pour toutes les afficher en même temps). Il s’agit plutôt d’une tentative pour représenter les outils disponibles en partant du besoin de l’utilisateur plutôt que des outils eux-mêmes : il est facile de consulter une page de manuel si l’on sait quelle page consulter. La commande apropos et le web permettent en général de trouver quelle commande utiliser mais cela reste parfois difficile lorsque l’on ne sait pas définir exactement son problème.

Lorsqu’il y a plusieurs commandes sur le même noeud, cela signifie qu’elles peuvent être utilisées dans le même but mais selon les préférences, les habitudes ou leur disponibilité (si elles sont installées ou non sur le système), on pourra préférer l’une ou l’autre d’entre elles. Par exemple, à titre personnel, j’apprécie most comme lecteur de fichier, entre autres pour la coloration des pages de manuel, mais le paquet n’est pas installé par défaut sous Debian et dérivées. Dans ce cas-là, less est la solution. Je ne cite pas more, réservé aux fans de masochisme hardcore. Autant utiliser cat, il y a un caractère de moins à taper.

Parfois des paramètres sont ajoutées à la commande car ils sont nécessaires pour l’obtention du résultat attendu. Pour autant, l’utilisateur ne devrait pas faire l’économie de regarder les autres options s’il désire un résultat un peu différent.

La plupart des outils cités sont très connus. À part peut-être cal (inclus dans le paquet bsdmainutils dans Debian), concalc (paquet concalc), fold (inclus dans le paquet coreutils) ou tree (paquet tree) ?

Rappelons que la puissance du shell ne se résume à des outils mais bien dans leur combinaison. Si elle ne suffit pas, rien n’empêche d’utiliser un langage de script de plus haut niveau (Perl, Python, Ruby, etc.).

Sources

Carte réalisée avec Freeplane v.1.1.3.
D’autres logiciels existent :

  • Freemind, Vym (directement dans Debian) ;
  • xmind, labyrinth, etc. (non packagés).

Le fichier source .mm est disponible ici.

D’autres personnes ont déjà réalisés des cartes heuristiques comme ici ou .

http://screenshots.debian.net est un site regroupant des captures d’écran de logiciels en actions qui sont disponibles comme paquet dans Debian. L’envoi de captures d’écran de paquets pour compléter le site est ouvert à tous. Les captures sont aussi réutilisées ailleurs, par exemple dans synaptic.

21 décembre 2011

Supprimer des lignes identiques réparties dans un fichier

Jules et Vincent doivent fournir un fichier texte en supprimant les lignes qui sont plusieurs fois dans le fichier, mais réparties de manière quelconque dans le fichier (par exemple un fichier journal ou une liste de nombres aléatoires). Alors qu’ils descendent de la voiture pour aller sur le lieu de leur mission, ils en discutent nonchalamment :
– Il nous faudrait des outils Unix pour ces affaires-là.
– Y’a combien de lignes ?
– 1.200
– En comptant les doublons ?
– Oui.
– Faudrait des outils Unix…

Après un moment de réflexion plus ou moins court (selon votre taux de caféine), comme eux, vous vous dites que cela ne devrait vous prendre que quelques secondes, le temps de dégainer un terminal et de taper une commande Unix adéquate…

Solutions basées sur le shell

uniq est un outil shell permettant de supprimer des lignes répétées. Voilà qui semble parfait pour ce genre d’affaire. Malheureusement, en lisant un peu plus la page de man, on apprend qu’uniq filtre « les lignes successives identiques ». La page de man propose un contournement en utilisant sort. Avec un fichier de log, cela peut être plus ou moins utilisable en triant d’abord par la chaîne de log puis par la date. En revanche, cela ne peut pas vraiment résoudre le problème de valeurs aléatoires. En revanche, il est possible de combiner plusieurs outils Unix en utilisant un compteur de ligne, qui sera supprimé ensuite.

Soit un fichier nommé pulp.txt et contenant les données suivantes :

1994-10-26
cheese
1994-10-26
1994-10-26
tarte
myrtille
1994-10-26
chalumeau
1994-10-26
1994-10-26
verset
massage

Commençons par ajouter un compteur de ligne :

$ nl pulp.txt
     1	1994-10-26
     2	cheese
     3	1994-10-26
     4	1994-10-26
     5	tarte
     6	myrtille
     7	1994-10-26
     8	chalumeau
     9	1994-10-26
    10	1994-10-26
    11	verset

Puis on trie en fonction des données préalablement fournies, tout en éliminant des chaînes en doubles en même temps :

$ nl pulp.txt | sort --key 2 --unique
     1	1994-10-26
     8	chalumeau
     2	cheese
     6	myrtille
     5	tarte
    11	verset

On réordonne selon l’ordre précédent :

$ nl pulp.txt | sort --key 2 --unique | sort --key 1 --numeric-sort
     1	1994-10-26
     2	cheese
     5	tarte
     6	myrtille
     8	chalumeau
    11	verset

Pour finir, on supprime la numérotation :

$ nl pulp.txt | sort --key 2 --unique | sort --key 1 --numeric-sort | cut --fields 2
1994-10-26
cheese
tarte
myrtille
chalumeau
verset

Le problème est alors résolu, mais et la mise au point aura probablement pris plus de temps que prévu (selon votre taux d’alcoolémie) :

nl pulp.txt | sort –key 2 –unique | sort –key 1 –numeric-sort | cut –fields 2

Cependant cette succession de commande ne sera directement réutilisable dès que la structure des chaînes variera (même un tout petit peu).

Il est regrettable qu’il y ait pas une option permettant de filtrer l’ensemble des lignes par uniq. Si jamais vous êtes en train de faire une overdose de shell, demandez à votre voisin de vous faire une piqûre d’adrénaline. (Attention, ça ne fonctionne pas à chaque fois.) Le mainteneur d’uniq refuse l’ajout d’une telle fonctionalité à cause de l’augmentation de la complexité que cela provoquerait. Par contre, des solutions bien plus compactes de contournement ont été proposées sur la liste de diffusion de coreutils.

One-liners

On se repoudre le nez et on y retourne !

Les premières solutions ont été à base de Perl :

perl -lne ‘print $_ if ! defined $a{$_}; $a{$_}=$_;’

perl -MDigest::MD5=md5 -lne ‘$m=md5($_); print $_ if ! defined $a{$m}; $a{$m}=1′

$_ représente la ligne en cours de traitement ; elle est affichée si ce n’est pas une clef d’un tableau associatif puis on ajoute la chaîne comme clef. La seconde version reprend ce même principe en utilisant une signature md5. Perl est vraiment adapté à l’écriture de code d’une ligne : c’est compact et illisible. Ce qui est tout de même un grand principe de Perl : « il y a plus d’une façon de le faire », mais on choisira toujours la plus incompréhensible. ;)

Puis une solution en awk a été proposée :

awk ‘!a[$0]++’

La ligne traitée est $0 ; la valeur d’un tableau a ayant pour clé la ligne en cours de traitement est incrémentée. Si c’est la deuxième fois qu’elle est rencontrée, la valeur sera non nulle. Le ! inverse le résultat qui sera donc évalué à faux (la chaîne est déjà présente).

Ces solutions résolvent le problème, de manière plus souple que la suite de commandes précédentes. Par contre, elles ne résolvent pas le problème de complexité. Comme cela est réalisé par un interpréteur plutôt que du code C compilé (pour uniq), il est quasi-certain que la consommation mémoire est plus importante et que la vitesse d’exécution est plus lente… Je ne pense pas que ce soit un problème mais la réponse est pire que le contre-argument de ne pas le réaliser via uniq.
Pour autant, cela ne m’a pas apparu nécessaire de tenter de convaincre à nouveau le mainteneur. C’est comme masser les pieds de la femme du parrain de la pègre locale. Vous le feriez, vous ? Moi non plus.

Mise en place d’un alias

Pour garder le filtre à disposition, il est possible d’en faire un alias. Pour cela, il suffit de copier la ligne suivante in ~/.bash_aliases (si ce fichier est activé dans ~/.bashrc) :

alias uniqall=’awk ‘”‘”‘! a[$0]++’”‘”

Alors qu’ils sont sur la route du retour, Vincent a les mains sur le clavier et un cahot de son fauteuil à roulette fait partir d’un coup une série de caractères supplémentaires !
Vincent : Oh putain le con j’ai ajouté plein d’apostrophes et de guillemets !
Jules : Mais pourquoi t’as fait ça putain ?
Vincent : Mais parce qu’il le fallait, c’est pas un accident !

En effet, Vincent était obligé : la commande awk ou perl fonctionne très bien seule mais elle ne peut pas être insérée directement comme alias. En effet, il faut transformer la commande en chaîne de caractère pour l’insérer dans le fichier .bash_aliases, donc mettre des apostrophes autour de la commande. Or, il y a déjà des apostrophes à l’intérieur de la commande (interpréteur 'code'). On aurait donc des apostrophes incluses entre d’autres apostrophes et le shell interprèterait la seconde apostrophe comme la fin de la première chaîne. Quelques solutions semblent évidentes :

  • Protéger les apostrophes intérieures avec un antislash (\') ;
  • Remplacer les apostrophes intérieures par des guillemets ;
  • Remplacer les apostrophes extérieures par des guillemets.

Ces différentes stratégies vont d’un fonctionnement incorrect (il ne retourne que la première ligne du flux) à une erreur lors de l’ajout de l’alias.

Explication du ‘”‘”‘

La ruse est de découper la commande en plusieurs sous-chaînes qui seront concaténées automatiquement par le shell.

Il est tout à fait possible de mettre des espaces à l’intérieur des chaînes mais pas entre elles. Sinon le shell les interprétera comme des mots différents et ne les concatènera pas.

Générique de fin

Merci aux participants de liste de diffusion bug-coreutils qui ont été très réactifs : Pádraig Brady, Jim Meyering et Bob Proulx (le rapport de bug, début de la discussion).

Merci à Arthur et Colin qui m’ont suggéré d’en faire un article. (Ils ne pensaient pas que j’allais vous faire subir un article de plus de 50 tweets de longueur…)

Les discussions de Vincent et de Jules sont des références à Pulp Fiction. (liste non exhaustive)

Le shell utilisé est bash, version 4.2.20. L’interpréteur Awk est mawk, version 1.3.3.

Aucun compilateur n’a été maltraité durant l’écriture de cet article, ni lors de la mise au point de l’alias final.

28 octobre 2011

Publications Debian sur une ligne du temps

La distribution Debian est connue pour donner des codes de personnage de Toy Story aux différentes distributions publiées. Il y a aussi un numéro mais c’est tout de même moins amusant. L’idée a depuis été reprise par Ubuntu et Fedora, mais en utilisant d’autres thèmes. Android fait de même avec son API. Même Apple a réutilisé le concept. Il est cependant probable que l’idée avait déjà été utilisée avant Debian…

Vers l’infini et au-delà ! (mais quand ce sera prêt)

Voici le résultat si l’on met chaque version sur une frise chronologique. Le segment jaune de la ligne de temps correspond à une période où il n’y avait pas encore de noms de code. Les noms de code pouvaient difficilement apparaître avant la sortie de Toy Story… Ils ont été ajoutés à partir de la première version officielle : la 1.1, surnommée Buzz.

On voit bien le changement de rythme entre les premières années et la suite, la loooooooooooongue période de développement de Sarge et la régularité des publications suivantes.

La prochaine version aura pour nom de code Wheezy, un personnage qui apparaît dans le deuxième épisode de Toy Story. Après la période sans nom de code, puis celle des noms du premier film, peut-être est-ce le début d’une troisième période pour les noms de code de la distribution ?

Sources

L’image a été réalisée avec The Gimp.

Les personnages sont principalement tirés de fonds d’écran distribués par Pixar, retouchés pour l’occasion (trouvables, par exemple sur pixar.wikia.com).

La ligne de temps est un bricolage fait avec Calc (LibreOffice) et la touche Impr écran.

Correctifs

Merci à TomThePhysicist, la honte et l’opprobre sont sur moi : je me suis trompé dans la frise comme l’atteste les commentaires. La version dans l’article prend en compte ces remarques. Je ferai pénitence en écrivant plus de 65.000 de lignes de code en {insérez ici votre langage détesté}, sans indentation et sans parenthèse.
Merci aussi à Elessar, je ne retrouvais plus le terme exact en français.

28 septembre 2011

Carte de répartition des développeurs Debian dans le monde

Tout comme la répartition des éléphants de mers ou des Edelweiss, celle des informaticiens n’est pas homogène à travers le monde. Concernant les Edelweiss et les informaticiens, il semble assez évident que les pays du Nord sont plus fournis que ceux du Sud. En se restreignant aux informaticiens, la propriété reste vraie, que l’on parle de logiciel propriétaire ou de logiciels libres. Pour illustrer ce dernier cas, on peut voir une mappemonde des développeurs Debian directement sur le site de la distribution.

Un développeur Debian (noté DD par la suite) est un membre du projet Debian, ayant un droit de vote au sein du projet et ayant la possibilité d’envoyer de nouvelles versions de n’importe quel paquet. Il existe un processus de validation pour pouvoir devenir DD. L’entrée et la sortie de Debian étant relativement lente, les variations de population sont assez faibles.

Un cartogramme est une carte géographique, déformée selon le critère que l’on souhaite mettre en évidence, de manière à sur-représenter (ou sous-représenter) une zone dans le but de mieux visualiser les différences. C’est une anamorphose appliquée à une carte. Voici deux cartogrammes sur la répartition des DD dans le monde en Juin 2011 :

Répartition en valeur absolue

Le critère utilisé est le nombre de DD actifs par pays.

Assez logiquement, les pays industrialisés avec une forte population s’en sortent mieux. Debian est surtout développée en Europe et aux États-Unis mais cette caractéristique était déjà visible sur la carte fournie par Debian. L’Afrique disparaît complètement à l’exception de l’Afrique du Sud et de Madagascar.

Répartition en valeur relative

Le critère utilisé est le ratio entre le nombre de DD actifs et le nombre d’habitants dans un pays.

Les pays peu peuplés sont mieux représentés : ceux qui était déjà visibles explosent (en particulier l’Irlande et la Nouvelle-Zélande). Les États-Unis font un assez mauvais score alors que l’Europe domine la carte. Les pays de l’Europe du Nord sont beaucoup plus visibles (Danemark, Norvège, Suède et surtout la Finlande). Cette dernière a le record en valeur relative avec 3,9 DD actifs par millions d’habitants. L’inde disparaît, écrasée par sa population.

Sources

Anamorphoses réalisées avec ScapeToad, un logiciel libre écrit en Java, puis légèrement retouchée.

La carte des pays vient de thematicmapping.org (l’archive TM_WORLD_BORDERS-0.3).

Le décompte des développeurs Debian a été réalisé par Christian Perrier, infatiguable DD, en Juin 2011. Il s’est basé sur les données fournies directement par Debian. Les cartes réalisées utilisent les statistiques de développeurs considérés comme actifs.

Suivre

Get every new post delivered to your Inbox.