Table of Contents

16h45 - TP « Dénuméroteur de lignes »

Navigation rapide : Lundi / Mardi / Mercredi / Jeudi / Vendredi Mémos : Perl / Python / Ruby

Objectif

Le but du TP est d'avoir un script qui supprime les numéros de lignes des exemples de code fournis sur ce wiki.

Sujet

Nous allons écrire un filtre qui supprime les numéros de lignes d'un fichier texte. Les lignes numérotées commencent par zéro ou plusieurs espaces, suivis d'un ou plusieurs chiffres, immédiatement suivis de :, suivi éventuellement d'un espace.

Exemple

Si le programme s'appelle myprog, voici comment on doir pouvoir l'utiliser :

$ cat fichier
 1: # .bashrc
 2:
 3: # Source global definitions
 4: if [ -f /etc/bashrc ]; then
 5:         . /etc/bashrc
 6: fi
 7:
 8: # User specific aliases and functions
$ ./myprog < fichier
# .bashrc

# Source global definitions
if [ -f /etc/bashrc ]; then
        . /etc/bashrc
fi

# User specific aliases and functions
$

Etape 1

Question

Un filtre est un programme qui prend les données à traiter sur stdin et écrit ses résultats sur stdout. Ecrire un filtre qui réécrit sur stdout tout ce qui lui arrive sur stdin.

Réponse

bash

1: #!/bin/bash
2: # Première version construite autour d'une boucle
3: while read LINE
4: do
5:   echo "$LINE"
6: done < /dev/stdin

bash

1: #!/bin/bash
2: # Seconde version sans boucle
3: cat - < /dev/stdin

perl

1: #!/usr/bin/perl
2:
3: while(<>)
4: {
5:   print ;
6: }

Remarques à propos de ce programme Perl

  • ce programme est un équivalent simplifié de la commande 'cat'
  • ce programme peut être appelé aussi bien par
./myprog < fichier

que par

./myprog fichier

et que par

./myprog f1 f2 g*
  • la boucle mémorise chaque ligne du fichier dans une variable implicite $_.
  • les fonctions prédéfinies ont parfois un argument facultatif qui, s'il est omis, est remplacé par $_. C'est le cas de la fonction print. La ligne est équivalente à :
print $_ ;

python version simple

1: #!/usr/bin/python
2: # -*- coding: utf-8 -*-
3: """Filtre trivial. Ne gère que l'entrée standard"""
4:
5: import sys
6:
7: for line in sys.stdin():
8:     print line,

python version avec fileinput

1: #!/usr/bin/python
2: # -*- coding: utf-8 -*-
3: """Filtre trivial. Gère aussi les fichiers passés en paramètres."""
4:
5: import fileinput
6:
7: for line in fileinput.input():
8:     print line,

ruby

1: $stdin.each_line { |line|
2:     puts line
3: }

Etape 2

Question

Ecrire un filtre qui supprime les numéros des lignes lues sur stdin.

Réponse

bash

1: #!/bin/bash
2: # Première version avec une boucle : à éviter car lance un processus par ligne => couteux
3: while read LINE
4: do
5:   echo "$LINE" | sed -e 's/^\s*[0-9]\+: \{0,1\}//g'
6: done < /dev/stdin

bash

1: #!/bin/bash
2: # Seconde version ne lançant qu'un seul processus
3: sed -e 's/^\s*[0-9]\+: \{0,1\}//g' < /dev/stdin

perl

1: #!/usr/bin/perl
2:
3: while(<>)
4: {
5:   s/^ *\d+: ?// ;     # on supprime le numéro
6:   print ;
7: }

Remarques à propos de ce programme Perl

  • le substitute s'applique à la variable $_ ; c'est équivalent à
$_ =~ s/^ *\d+: ?// ;

python

1: import fileinput
2: import re
3:
4: for line in fileinput.input():
5:     print re.sub('^\s*\d+: ?','',line),

python avec re compilée

1: import fileinput
2: import re
3:
4: p = re.compile('^\s*\d+: ?')
5: for line in fileinput.input():
6:     print p.sub('',line),

ruby

1: $stdin.each_line do |line|
2:         puts line.gsub(/^\s*\d+:\s*/,'')
3: end

Version

$Id: denumeroteur.txt 682 2012-05-28 17:22:12Z jaclin $