2017-06-23 5 views
1

Ich versuche, eine beliebige Anzahl Zeichenfolge wie 3.1415926535897932384626433832795028841971 direkt nach jeder 0 oder Gruppe 0 zu teilen. Allerdings möchte ich die 0 nach jeder Gruppe behalten.Split-String mit Lookahead/Lookbehind mit leeren String

Zum Beispiel der Zeichenfolge 10203040506070809011 sollte in

['10', '20', '30', '40', '50', '60', '70', '80', '90', '11'] 

aufgeteilt werden und die Zeichenfolge 3.1415926535897932384626433832795028841971 sollte in

['3.14159265358979323846264338327950', '28841971'] 

aufgeteilt wird Ich habe versucht, die Zeichenfolge mit einem positiven Lookbehind zu spalten auseinander und einem leeren string:

import re 
p = '(?<=0+)' 

re.search(p, '102030405') 
><_sre.SRE_Match object; span=(2, 2), match=''> 

'102030405'.split(p) 
>['102030405'] 

aber dies tut die Zeichenfolge überhaupt nicht aufteilt, obwohl das Muster übereinstimmt.

Ich versuchte auch nur die Zeichenfolge auf der Grundlage der 0 Zerlegung auseinander und fügen Sie eine 0 nach den ersten paar Strings, aber es scheint gewunden und ineffizient.

Gibt es eine Möglichkeit, eine Zeichenfolge basierend auf einem Lookahead oder Lookbehind auf einer leeren Zeichenfolge zu teilen? Ich frage nach dem allgemeinen Fall, nicht nur nach Zahlen. Zum Beispiel, wenn ich 3:18am5:19pm10:28am in die separaten Zeiten teilen wollte, ohne die am oder pm zu verlieren, und ein Array ['3:18am', '5:19pm', '10:28am'] bekommen, wie würde ich darüber gehen, dies zu tun?

+0

Welche Version von Python verwenden Sie? Ich erhalte einen Fehler, wenn ich versuche 're.search (p, '102030405')' ' –

+0

Verwenden von Python 3.6.1 – victor

+0

Wie möchten Sie' '10020'' spalten? "['100', '20']" oder "['10', '020']" – randomir

Antwort

1

Diese einfache regex in re.findall sollte ausreichen:

l = re.findall(r'[.1-9]+(?:0+|$)', s) 

Hinweis:

  • findall kehrt alle nicht- überlappend passt von Muster in String, als Liste von Strings.

  • für jedes Spiel wir die längste Kette von Ziffern (oder einen Punkt) endet mit mindestens einer Null, oder das Ende des

  • die Nullen am Ende Zeichenfolge wollen, sollten nicht als ein anderes Spiel aufgenommen werden (daher die (?:...)

Ebenso für Sie zweites Beispiel:

>>> re.findall(r'[\d:]+(?:am|pm|$)', '3:18am5:19pm10:28am') 
['3:18am', '5:19pm', '10:28am'] 

Keine Notwendigkeit für Look-Ahead/Lookbehind Magie oder nicht-gre Edy Matching.

1

Verwendung re.findall:

l = re.findall(r'(?<![^0])[1-9.]+0*', s) 

Der Schlüssel ist eine doppelte Negation zu verwenden: nicht und voraus, der nicht Null (a vorhergehenden Null oder den Beginn der Zeichenfolge übereinstimmen)

1

Python split erfordert eine Übereinstimmung ungleich Null.

Sie können findall mit dieser Regex verwenden, um Ihre Matches zu erhalten:

>>> print re.findall(r'([\d.]+?(?:0+|$))', '10203040506070809011') 
['10', '20', '30', '40', '50', '60', '70', '80', '90', '11'] 

>>> print re.findall(r'([\d.]+?(?:0+|$))', '3.1415926535897932384626433832795028841971') 
['3.14159265358979323846264338327950', '28841971'] 

([\d.]+?(?:0|$)) entspricht Ziffer oder Punkt, der mit 0 oder Ende der Zeile endet.


Update:

Jedoch habe ich von Ihrer editierten Frage beachten und Kommentare, die Sie für eine generische Lösung gesuchte Null-Breite regex Muster für den Split-Betrieb zu verwenden.

Ich schlage vor, Sie installieren sehr nützlich regex module in Python. Version 1 dieses Moduls bietet die meisten PCRE-Funktionen und weit überwiegt das Standardmodul re.

Die Installation ist ziemlich einfach.Laden Sie einfach die tar gzip-Datei von Link oben und führen Sie dann:

sudo python setup.py install 

Aus dem Inneren des Verzeichnis, das Sie nach dem Extrahieren der tar-Dateien. (Ignorieren Sie einige Warnungen im Installationsvorgang).

Sobald regex installiert ist nur diesen Code verwenden:

>>> import regex 

>>> regex.DEFAULT_VERSION = regex.VERSION1 

>>> regex.split(r'(?<=[ap]m)(?=.)', '3:18am5:19pm10:28am') 
['3:18am', '5:19pm', '10:28am'] 

>>> print regex.split(r'(?<=0)(?=[1-9])', '10203040506070809011') 
['10', '20', '30', '40', '50', '60', '70', '80', '90', '11'] 

>>> print regex.split(r'(?<=0)(?=[1-9])', '3.1415926535897932384626433832795028841971') 
['3.14159265358979323846264338327950', '28841971'] 

>>> print regex.split(r'(?<=0)(?=[1-9])', '10020') 
['100', '20'] 
+1

Stimmt es, dass es niemals eine Situation geben wird, die ich ohne Lookahead oder Lookbehind nicht lösen kann? Meine ursprüngliche Frage war, leere Strings mit einem bestimmten Lookahead/Lookbehind abzustimmen, aber jetzt, da ich darüber nachdenke, kann ich mir keinen Fall vorstellen, in dem das die einzige Wahl ist. – victor

+1

ja das stimmt. Wir können das Problem immer lösen, indem wir Regex wie in diesem Beispiel bearbeiten. Es wäre sicher schön gewesen, wenn Python eine leere oder nullbreite Übereinstimmung für die Übereinstimmung/Aufteilung zulassen würde. – anubhava

Verwandte Themen