1
votes

Regex pour faire correspondre les entrées entre les barres obliques, mais pas les barres obliques - y compris les entrées vides

J'essaie d'utiliser une expression régulière pour faire correspondre les entrées entre les barres obliques dans le texte ci-dessous:

311102Z/5663.00N/00813.02E/GPS//03/-/

Pour cet exemple, les résultats devraient être une série de correspondances qui ont le contenu:

  • 311102Z
  • 5663.00N
  • 00813.02E
  • GPS
  • (une chaîne vide)
  • 03
  • -

Il est important d'attraper l'entrée vide et de renvoyer une correspondance vide. Malheureusement, pour diverses raisons, nous ne pouvons pas utiliser le regroupement ici, ni faire correspondre les barres obliques elles-mêmes et les diviser.

J'ai le regex suivant comme quelque chose qui fonctionne presque: (. *? ) (? = /) . Un affichage interactif de cette expression régulière peut être vu ici . Il correspond bien à toutes les entrées, mais a des correspondances vides supplémentaires à la fin de chaque entrée.

J'ai essayé de remplacer le * par un + , mais bien sûr, cela signifiait qu'il ne correspondait pas à l'entrée vide.

Quelqu'un a-t-il des idées sur ce que je pourrais faire pour que cela corresponde à ce que je veux - c'est-à-dire. sans ces correspondances vides supplémentaires, mais avec l'entrée vide à la position où il n'y a pas de caractères entre les barres obliques.

Si c'est important pour la compatibilité, J'utilise cette regex en Python.


8 commentaires

Pourquoi avez-vous besoin d'utiliser une regex? On dirait que vous pourriez simplement utiliser str.split ("/") ?


Vous pouvez simplement utiliser ([^ /] *) / comme expression régulière voir la démo: regex101.com/r/AGMfuk/2


@PeterH. Malheureusement pour la compatibilité avec le reste du système, nous devons utiliser une regex pour cela - comme toutes les autres lignes que ce code doit traiter nécessitent une regex pour se diviser.


@anubhava Merci, mais malheureusement, nous devons avoir la correspondance complète sans la barre oblique à la fin, encore une fois en raison d'autres exigences du système, nous ne pouvons pas simplement sélectionner le premier groupe. Par «correspondance complète», j'entends ici que chacune des correspondances de ma liste à puces doit être le contenu complet du match, et non le contenu d'un groupe dans le match.


lst = s [: - 1] .split ('/') aiderait-il? Où s est votre chaîne?


Cette question ressemble à un problème xy


@Ruzihm, je ne vois pas pourquoi. Le PO a clairement énoncé le problème sans faire référence à une approche à adopter.


@CarySwoveland utilisant une expression régulière est l'approche supposée pour une vague «compatibilité».


5 Réponses :


4
votes

Vous pouvez utiliser cette expression régulière avec des assertions lookahead et lookbehind:

>>> import re
>>> s = '311002Z/3623.00N/00412.02E/GPS//03/-/'
>>> print (re.findall(r'(?:(?<=/)|^)[^/]*(?=/)', s))
['311002Z', '3623.00N', '00412.02E', 'GPS', '', '03', '-']

Démo RegEx

(?:(?<=/)|^)[^/]*(?=/)

Détails RegEx: p>

  • (?: (? : Regardez derrière pour affirmer que nous avons soit start, soit / à la position précédente
  • [^ /] * : correspond à 0 ou plus de tout caractère qui n'est pas /
  • (? = /) : Lookahead pour affirmer que nous avons un / devant


0 commentaires

0
votes

Vous pouvez utiliser re.split pour cela (comme str.split , en utilisant uniquement une expression régulière), puis en supprimant le dernier élément:

>>> import re
>>> foo = "311102Z/5663.00N/00813.02E/GPS//03/-/"

>>> re.split("/", foo)[:1]
['311102Z', '5663.00N', '00813.02E', 'GPS', '', '03', '-']


1 commentaires

C'était ma première suggestion à OP dans les commentaires mais malheureusement OP ne peut pas utiliser de groupes de capture.



0
votes

Ensuite, je suggérerais:

['311102Z', '5663.00N', '00813.02E', 'GPS', '', '03', '-']

qui renvoie

import re
 
entry = "311102Z/5663.00N/00813.02E/GPS//03/-/" 
  
match = re.findall("([^/]*)/", entry)  
print(match)


2 commentaires

C'était ma première suggestion à OP dans les commentaires mais malheureusement OP ne peut pas utiliser de groupes de capture.


On dirait qu'OP a une base de code problématique alors :)



3
votes

Comme alternative, vous pouvez faire correspondre plus de 1 fois n'importe quel caractère sauf / , en affirmant un / sur la droite.

Ou obtenir la position entre 2 barres obliques .

'311102Z', '5663.00N', '00813.02E', 'GPS', '', '03', '-']

Explication

  • [^ /] + (? = /) Correspond à plus de 1 fois n'importe quel caractère sauf / et affirmez un / à droite
  • | Ou
  • (? Obtenir la position entre 2 barres obliques

Démo Regex | Démo Python

Exemple de code

import re
 
s="311102Z/5663.00N/00813.02E/GPS//03/-/"
pattern = r"[^/]+(?=/)|(?<=/)(?=/)"
print(re.findall(pattern, s))

Sortie

[^/]+(?=/)|(?<=/)(?=/)


0 commentaires

1
votes

Encore un (Python):

(?<=/)  : use a positive lookbehind to assert match is preceded by '/'
(?=/)   : use a positive lookahead to assert match is followed by '/'
|       : or
[^/]+   : match 1+ characters other than '/'

Démarrez votre moteur !

(?<=/)(?=/)|[^/]+

Remplacez [^ /] + par [^ / \ n] + pour empêcher correspond à des terminateurs de ligne couvrant.


1 commentaires

Bonjour, j'ai publié une question aujourd'hui stackoverflow.com/questions/62607380/... , Si vous connaissez une nouvelle façon de résoudre le problème, pouvez-vous y poster?