1
votes

Comment diviser une chaîne et y conserver les séparateurs

@edzech a demandé comment était-il possible de diviser une chaîne et d'y conserver les séparateurs. Sa question a été marquée comme dupliquée , alors que l'approche ici est différente de la "duplication" .

Nous voulons diviser une chaîne mais en y gardant les délimiteurs, nous ne voulons pas qu'ils soient séparés. En bref, pour dghi , nous voulons:

['<', 'abc', '>' 'd', '<', 'e', '>', '<', 'f', '>', 'ghi', '<', 'j', '>']

au lieu de: p >

['<abc>', 'd', '<e>', '<f>', 'ghi', '<j>']

Utiliser split n'aide pas car il sera fractionné en fonction du séparateur. Nous voulons le garder attaché à son contenu.


0 commentaires

3 Réponses :


1
votes

Voici la solution.

['<abc>', 'd', '<e>', '<f>', 'ghi', '<j>']

Résultat:

import re

content = "<abc>d<e><f>ghi<j>"
result = re.findall(r"<.*?>|[^<>]+", content)

print(result)

Explications:

  • regex <.> signifie tout ce qui correspond à
  • regex [^ ] + signifie tout le reste

En bref, findall trouvera tout ce qui correspond à , sinon, tout le reste. De cette façon, le contenu sera divisé sans perdre les séparateurs.


0 commentaires

1
votes

Je pense que vous pouvez utiliser split avec cette expression régulière

>>> import re
>>> rx = re.compile( r"(?<=>)(?=[a-z<])|(?<=[a-z>])(?=<)" )
>>> s = "<abc>d<e><f>ghi<j>test><g>"
>>> x =  re.split( rx, s )
>>> print ( x )
['<abc>', 'd', '<e>', '<f>', 'ghi', '<j>', 'test>', '<g>']

https : //regex101.com/r/WNy5n9/1

Ce n'est rien de plus que 2 options avec des assertions lookbehind / ahead appariées.

Développer

>>> import sys
>>> print( sys.version )
3.7.3 (v3.7.3:ef4ec6ed12, Mar 25 2019, 21:26:53) [MSC v.1916 32 bit (Intel)]

Update
Notez que dans les versions de Python antérieures à la version 3.7, la division
sur une correspondance vide n'a pas été gérée correctement.
Vraisemblablement, ils ne pouvaient pas faire la différence entre un vide
string et / ou comment effectuer le déplacement sur des correspondances de largeur nulle.

On dirait qu'ils ont sorti la tête de leur ** maintenant dans la version 3.7,
alors voilà.

Démo

Version 3.7.3

   (?<= > )                      # Behind a  >
   (?= [a-z<] )                  # Ahead either a-z or <
|                              # or,
   (?<= [a-z>] )                 # Behind either a-z or >
   (?= < )                       # Ahead a  <

Code p>

(?<=>)(?=[a-z<])|(?<=[a-z>])(?=<)


0 commentaires

1
votes

Dans la solution proposée, une seule ouverture ou fermeture > qui ne fait pas partie d'une paire est exclue du résultat.

Si vous aussi souhaitez conserver un ou > que vous pourriez utiliser:

['<abc>', 'd', '<e>', '<f>', 'ghi', '<j>', 'test>', '<g>']

Explication

  • *> Correspond à l'ouverture , puis plus de 0 fois pas > , puis une fermeture >
  • | Ou
  • (?: (?! ] *>).) + Jeton gourmand tempéré, correspond à n'importe quel caractère si ce qui est directement à droite n'est pas le modèle d'ouverture jusqu'à la fermeture

Démo Regex | Démo Python

Par exemple:

import re
content = "<abc>d<e><f>ghi<j>test><g>"
result = re.findall(r"<[^<>]*>|(?:(?!<[^<>]*>).)+", content)
print(result)

Résultat

<[^<>]*>|(?:(?!<[^<>]*>).)+


0 commentaires