IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

[re] Splitter une chaîne avec ponctuation et accents


Sujet :

Python

  1. #1
    Membre du Club Avatar de Tryp'
    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    48
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations forums :
    Inscription : Novembre 2008
    Messages : 48
    Points : 53
    Points
    53
    Par défaut [re] Splitter une chaîne avec ponctuation et accents
    Bonjour à vous,

    Je cherche effectivement à découper une chaîne en Python sur les espaces (comme la méthode split), mais aussi sur la ponctuation. Malheureusement, ce n'est pas aussi facile, en particulier quand les caractères accentués entrent aussi dans la partie !

    Par exemple, voici ce que je recherche à faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    >>>> chaine = "Ma chaîne, très simple!!"
    >>>> regex = re.compile("...")
    >>>> mots = [mot for mot in re.split(regex, chaine) if mot.strip()]
    >>>> print mots
    ['Ma', 'chaîne', ',', 'très', 'simple', '!!']
    Voici les essais que j'ai déjà fait :
    Regex --> liste de retour

    "\W" --> ['Ma', 'cha', 'ne', 'tr', 's', 'simple'] : ni ponctuation, ni accent

    "(\W+)" --> ['Ma', 'cha', 'î', 'ne', ',', 'tr', 'è', 's', 'simple', '!!'] : ponctuation OK, mais les accents sont pris pour des délimiteurs
    (J'ai volontairement remplacé les chaînes \xxx par les accents)

    "\s" --> ['Ma', 'chaîne,', 'très', 'simple!!'] : accents OK, mais plus la ponctuation...


    J'ai aussi essayé d'ajouter des "flags" à la compilation de la Regex comme re.LOCALE ou re.UNICODE, mais en apparence rien ne change grandement.

    Après avoir passé la soirée à chercher, je viens demander votre soutien. Si quelqu'un a déjà été confronté au problème, ou possède une éventuelle réponse, je suis ouvert à toute proposition.

    En vous remerciant d'avoir pris le temps de me lire, et peut-être de m'aider, je vous souhaite une bonne journée.

    Cordialement.

    Ps : J'utilise Python 2.6 sur un GNU/Debian (cela est-il important ? On ne sait jamais !)

  2. #2
    Membre éprouvé

    Homme Profil pro
    Diverses et multiples
    Inscrit en
    Mai 2008
    Messages
    662
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Diverses et multiples

    Informations forums :
    Inscription : Mai 2008
    Messages : 662
    Points : 1 273
    Points
    1 273
    Par défaut
    Bon, d’abords, si tu veux travailler avec les accents, il est très fortement conseillé d’utiliser les chaînes unicode*!

    Voici un code qui marche (chez moi –*debian testing, python 2.6 )*:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    >>> chaine = u"Ma chaîne, très simple!!"
    >>> regex = re.compile(r"(\W+)", re.UNICODE)
    >>> mots = [mot.strip() for mot in re.split(regex, chaine) if mot.strip()]
    >>> print mots
    [u'Ma', u'cha\xeene', u',', u'tr\xe8s', u'simple', u'!!']


    [EDIT] En fait, en complexifiant un poil la regex, tu peux même te passer complètement de strip():

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    >>> chaine = u"Ma chaîne, très simple!!"
    >>> regex = re.compile(r"\s+|([^\w\s]+)", re.UNICODE)
    >>> mots = [mot for mot in re.split(regex, chaine) if mot]
    >>> print mots
    [u'Ma', u'cha\xeene', u',', u'tr\xe8s', u'simple', u'!!']
    Les performances semblent quasi-identiques…

  3. #3
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 049
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 049
    Points : 1 380
    Points
    1 380
    Par défaut
    sépare les ponctuations des mots puis split() la chaine.
    enfin, c'est comme ça que je ferai ...

    exemple sans regex:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    # -*- coding: utf-8 -*-
    >>> #!/usr/bin/env python
    >>> chaine = "Ma chaîne, très simple!!"
    >>> for c in ",.!;:": chaine = chaine.replace(c,' %s'%c)
    >>> print chaine.split()
    ['Ma', 'cha\xc3\xaene', ',', 'tr\xc3\xa8s', 'simple', '!', '!']
    heu non, ça donne pas ce que tu veux ... mal lu

  4. #4
    Membre du Club Avatar de Tryp'
    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    48
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations forums :
    Inscription : Novembre 2008
    Messages : 48
    Points : 53
    Points
    53
    Par défaut
    Tout d'abord, merci à tous les deux pour vos réponses !

    Citation Envoyé par mont29 Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    >>> chaine = u"Ma chaîne, très simple!!"
    >>> regex = re.compile(r"(\W+)", re.UNICODE)
    >>> mots = [mot.strip() for mot in re.split(regex, chaine) if mot.strip()]
    >>> print mots
    [u'Ma', u'cha\xeene', u',', u'tr\xe8s', u'simple', u'!!']
    Ça marche effectivement comme je le veux ! Alors, il fallait que ma chaîne soit au préalable en Unicode (ce que j'avais testé rapidement sans grand succès, je m'étais embrouillé en les fonctions .encode, .decode et unicode) !

    Mais que signifie clairement le 'r' devant la Regex ? Je sais que dans le cas Windows, ça permet de doubler les anti-slashs pour les noms de fichier, dans ce cas aussi alors j'imagine ? La "bonne" expression rationnelle serait donc "(\\W+)" si on omettait ce 'r' ?

    [EDIT] En fait, en complexifiant un poil la regex, tu peux même te passer complètement de strip():

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    >>> chaine = u"Ma chaîne, très simple!!"
    >>> regex = re.compile(r"\s+|([^\w\s]+)", re.UNICODE)
    >>> mots = [mot for mot in re.split(regex, chaine) if mot]
    >>> print mots
    [u'Ma', u'cha\xeene', u',', u'tr\xe8s', u'simple', u'!!']
    En effet ça marche également, mais je ne suis pas sûr de tout comprendre (dans l'expression rationnelle)
    Je sais que \s correspond à tout ce qui est un espace, ainsi que [^\w\s] correspond alors à tout ce qui n'est pas un espace ou un caractère.


    L'exemple de josmiley est plus clair à comprendre puisqu'il est sans regex, mais ne garde pas la ponctuation ensemble, dommage.

    Dans tous les cas, c'est très gentil à tous les deux de m'avoir aidé, je passe le sujet en résolu. Bonne continuation à vous.

  5. #5
    Membre éprouvé

    Homme Profil pro
    Diverses et multiples
    Inscrit en
    Mai 2008
    Messages
    662
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Diverses et multiples

    Informations forums :
    Inscription : Mai 2008
    Messages : 662
    Points : 1 273
    Points
    1 273
    Par défaut
    Citation Envoyé par Tryp' Voir le message
    Mais que signifie clairement le 'r' devant la Regex ? Je sais que dans le cas Windows, ça permet de doubler les anti-slashs pour les noms de fichier, dans ce cas aussi alors j'imagine ? La "bonne" expression rationnelle serait donc "(\\W+)" si on omettait ce 'r' ?
    Oui. le “r” indique une “raw string”, c’est-à-dire que \ n’est plus vu comme un méta-caractère d’échappement, mais comme un caractère normal… Sinon, quand on veut matcher un bête “\” dans une regex, il faut l’échapper deux fois (une pour la string, une pour la regex), ce qui donne “\\\\”, assez indigeste à la lecture…

    Citation Envoyé par Tryp' Voir le message
    En effet ça marche également, mais je ne suis pas sûr de tout comprendre (dans l'expression rationnelle)
    Je sais que \s correspond à tout ce qui est un espace, ainsi que [^\w\s] correspond alors à tout ce qui n'est pas un espace ou un caractère.
    Eh ben oui, c’est ça*! On “coupe” soit sur un ou plusieurs espaces, soit sur un ou plusieurs “tout ce qui n’est pas espace ni caractère alphanumérique” (donc, les ponctuations, essentiellement) –*en capturant ces derniers cas (la barre verticale, le “pipe”, signifie “ou”)…

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Sql Server 8.0]Requête dans une chaîne avec Cursor à executer
    Par Nicodemus dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 02/11/2006, 17h34
  2. [C#] Comment Splitter une string avec une string ?
    Par ADJ Design dans le forum C#
    Réponses: 12
    Dernier message: 27/07/2006, 12h10
  3. Réponses: 4
    Dernier message: 12/05/2006, 19h11
  4. [RegEx] Tester une chaîne avec ereg()
    Par Anduriel dans le forum Langage
    Réponses: 4
    Dernier message: 30/04/2006, 11h36
  5. [RegEx] Remplacer une chaîne avec preg_replace
    Par GregPeck dans le forum Langage
    Réponses: 3
    Dernier message: 08/12/2005, 12h21

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo