Manipulation de texte

Objectif : Regroupe des classes et des constantes utiles à la manipulation du texte.
Version : 2.5

Le module string nous vient des plus ancienne versions de Python. Lors du passage à la version 2.0, de nombreuses fonctions auparavant proposées par le module ont été transformées en méthodes de l'objet string. Les versions originales de ces fonctions ont été conservées dans le module string et sont abandonnées dans les versions 3.0 et suivantes de Python. Ce module contient par ailleurs d'autres constantes et classes utiles à la manipulation des objets string et unicode, Il sera ici question uniquement de ces éléments.

Constantes

Les constantes du module string sont utilisées pour désigner des catégories de caractères, comme ascii_letters ou digits. Certaines de ces constantes, par exemple lowercase, sont dépendantes des paramètres de configurations locaux (la langue notamment).

import string

for n in dir(string):
    if n.startswith('_'):
        continue
    v = getattr(string, n)
    if isinstance(v, basestring):
        print '%s=%s' % (n, repr(v))

La plupart des constantes sont nommées de façon explicite. (NdT : ci-après le résultat du script pour un système de langue anglaise )

$ python string_constants.py
ascii_letters='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
ascii_lowercase='abcdefghijklmnopqrstuvwxyz'
ascii_uppercase='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
digits='0123456789'
hexdigits='0123456789abcdefABCDEF'
letters='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
lowercase='abcdefghijklmnopqrstuvwxyz'
octdigits='01234567'
printable='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c'
punctuation='!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'
uppercase='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
whitespace='\t\n\x0b\x0c\r '

Fonctions

Deux fonctions n'ont pas été déplacées du module string.
capwords() met une majuscule à tous les mots d'une chaîne.

import string

s = 'The quick brown fox jumped over the lazy dog.'

print s
print string.capwords(s)

Le résultat est le même que si vous aviez appelé split(), mis une majuscule à tous les mots de la liste obtenue et enfin utilisé join() pour reconstruire la chaîne.

$ python string_capwords.py
The quick brown fox jumped over the lazy dog.
The Quick Brown Fox Jumped Over The Lazy Dog.

L'autre fonction, maketrans(), permet de créer une table de correspondance utilisable avec la méthode translate() du type string pour transformer un jeu de caractères en un autre.

import string

leet = string.maketrans('abegiloprstz', '463611092572')

s = 'The quick brown fox jumped over the lazy dog.'

print s
print s.translate(leet)

Dans cet exemple, certaines lettres sont remplacées par leur équivalent l33t.

$ python string_maketrans.py
The quick brown fox jumped over the lazy dog.
Th3 qu1ck 620wn f0x jum93d 0v32 7h3 142y d06.

Modèles

Les modèles (templates) de chaîne de caractères ont été ajoutés à la version 2.4 par la PEP 292. Ils sont censés être une alternative à la syntaxe de remplacement standard de Python. Avec le remplacement par string.Template les variables sont identifiées par un nom préfixé de $ (par exemple : $variable). S'il est nécessaire de les démarquer du texte environnant il est aussi possible de les entourer par des accolades (par exemple : ${variable}).

Cet exemple compare un modèle simple à un remplacement similaire (avec la syntaxe standard) :

import string

values = { 'var':'foo' }

t = string.Template("""
$var
$$
${var}iable
""")

print 'TEMPLATE:', t.substitute(values)

s = """
%(var)s
%%
%(var)siable
"""

print 'INTERPOLATION:', s % values

Comme vous pouvez le voir, le caractère qui déclenche le remplacement est répété deux fois pour éviter son interprétation.

$ python string_template.py
TEMPLATE:
foo
$
fooiable

INTERPOLATION:
foo
%
fooiable

Une différence clé entre les modèles et les remplacements standards est que le type des argumentes n'est pas pris en compte. Les valeurs sont converties en chaîne et insérées. Aucune option de formatage n'est disponible. Il n'y a, entre autre, aucune façon de contrôler le nombre de chiffres utilisés pour représenter un nombre à virgule.

Cependant, l'un des bénéfices de ce système est mis en évidence par la méthode safe_substitute(), avec laquelle il est possible d'éviter qu'une exception soit levée si toutes les valeurs nécessaires au modèle ne sont pas fournies en arguments.

import string

values = { 'var':'foo' }

t = string.Template("$var is here but $missing is not provided")

try:
    print 'TEMPLATE:', t.substitute(values)
except KeyError, err:
    print 'ERROR:', str(err)
    
print 'TEMPLATE:', t.safe_substitute(values)

Comme il n'y a pas de valeur pour la clé missing dans le dictionnaire, une exception KeyError est alors levée par la fonction substitute(). safe_substitute() pour sa part, ne lève pas d'exception, et dans ce cas le nom de la variable à remplacer est laissée en l'état dans le texte.

$ python string_template_missing.py
TEMPLATE: ERROR: 'missing'
TEMPLATE: foo is here but $missing is not provided

Modèle avancés

Si la syntaxe standard de string.Template ne vous convient pas, il est possible de changer son comportement en altérant les motifs (patterns) utilisés par l'expression régulière pour trouver le nom des variables à remplacer dans le modèle. La manière la plus simple d'y parvenir est de modifier les attributs delimiter et idpattern de la classe string.Template.

import string

class MyTemplate(string.Template):
    delimiter = '%'
    idpattern = '[a-z]+_[a-z]+'

t = MyTemplate('%% %with_underscore %notunderscored')
d = { 'with_underscore':'replaced', 
      'notunderscored':'not replaced',
      }

print t.safe_substitute(d)

Dans cet exemple, les noms des variables doivent comprendre en leur milieu un caractère de soulignement "_", ainsi %notunderscored n'est pas remplacé.

$ python string_template_advanced.py
% replaced %notunderscored

Il est également possible d'effectuer des changements plus complexes en remplaçant complètement l'attribut pattern. Le motif utilisé doit contenir 4 groupes nommés pour capturer la séquence correspondant à l'échappement du délimiteur, les noms de variables, les noms de variables entre crochets et les séquences invalides.

Voici le motif par défaut :

import string

t = string.Template('$var')
print t.pattern.pattern

Comme t.pattern est une expression régulière compilée, nous devons accéder à l'attribut pattern pour visualiser la chaîne correspondante.

$ python string_template_defaultpattern.py

    \$(?:
      (?P<escaped>\$) |   # Escape sequence of two delimiters
      (?P<named>[_a-z][_a-z0-9]*)      |   # delimiter and a Python identifier
      {(?P<braced>[_a-z][_a-z0-9]*)}   |   # delimiter and a braced identifier
      (?P<invalid>)              # Other ill-formed delimiter exprs
    )

Pour créer un nouveau type de modèle, qui utiliserait var comme syntaxe par exemple, nous pourrions utiliser ce motif :

import re
import string

class MyTemplate(string.Template):
    delimiter = '{{'
    pattern = r'''
    \{\{(?:
    (?P<escaped>\{\{)|
    (?P<named>[_a-z][_a-z0-9]*)\}\}|
    (?P<braced>[_a-z][_a-z0-9]*)\}\}|
    (?P<invalid>)
    )
    '''
    
t = MyTemplate('''
{{{{
{{var}}
''')

print 'MATCHES:', t.pattern.findall(t.template)
print 'SUBSTITUTED:', t.safe_substitute(var='replacement')

Il faut indiquer à la fois les motifs named et braced même si ce sont les même. Le script précédent produit la sortie suivante :

$ python string_template_newsyntax.py
MATCHES: [('{{', '', '', ''), ('', 'var', '', '')]
SUBSTITUTED:
{{
replacement

Fonctions obsolètes

La documentation de Python contient des informations sur les méthodes du module string qui ont été déclarées obsolètes et qui ont été déplacées dans les classes string et unicode.

Voir aussi

string

   La documentation officielle pour ce module.

PEP 292

   La PEP à l'origine de string.Template.

string – Working with text

   La version originale de ce PyMOTW