2009-11-30 11 views
17

Czy istnieje jakiś odpowiednik str.split w języku Python, który również zwraca separatory?tokenize string zachowujący ograniczniki w Pythonie

Potrzebuję zachować układ białych znaków dla mojego wyjścia po przetworzeniu niektórych tokenów.

Przykład:

>>> s="\tthis is an example" 
>>> print s.split() 
['this', 'is', 'an', 'example'] 

>>> print what_I_want(s) 
['\t', 'this', ' ', 'is', ' ', 'an', ' ', 'example'] 

Dzięki!

+1

+1 - Ciekawe pytanie, 'splitlines' wydaje się mieć' keepends' parametr, ale nie ma czegoś takiego dla 'split'. Wydaje się dziwne (http://docs.python.org/library/stdtypes.html#str.splitlines). –

Odpowiedz

19

Jak o

import re 
splitter = re.compile(r'(\s+|\S+)') 
splitter.findall(s) 
+0

elegancka i łatwa do rozbudowy (pomyśl '(\ s + | \ w + | \ S +)'). – hop

6
>>> re.compile(r'(\s+)').split("\tthis is an example") 
['', '\t', 'this', ' ', 'is', ' ', 'an', ' ', 'example'] 
4

moduł re zapewnia tę funkcję:

>>> import re 
>>> re.split('(\W+)', 'Words, words, words.') 
['Words', ', ', 'words', ', ', 'words', '.', ''] 

(cytat z dokumentacji Pythona).

Dla Twojego przykładu (podziel na białe znaki) użyj re.split('(\s+)', '\tThis is an example').

Kluczem jest zamknięcie wyrażenia regularnego, w którym ma nastąpić podział w przechwytywaniu nawiasów. W ten sposób ograniczniki zostaną dodane do listy wyników.

Edycja: Jak wskazano, wszelkie poprzedzające/końcowe znaczniki zostaną oczywiście dodane do listy. Aby tego uniknąć, możesz najpierw użyć metody .strip() na swoim łańcuchu wejściowym.

+0

nie używanie łańcucha OP maskuje fakt, że pusty łańcuch jest zawarty jako pierwszy element zwróconej listy. – hop

+0

Dzięki. Odpowiednio zredagowałem swój post (chociaż w tym przypadku specyfikacja PO ("chcę zachować białe znaki") i jego przykład były sprzeczne). –

+0

Nie, to nie było ... był jeden przykład obecnego zachowania i inny z pożądanego. – fortran

-1

Dzięki chłopaki za wskazanie dla modułu re, ja wciąż stara się zdecydować między tym i stosując własną funkcję, która zwraca ciąg ...

def split_keep_delimiters(s, delims="\t\n\r "): 
    delim_group = s[0] in delims 
    start = 0 
    for index, char in enumerate(s): 
     if delim_group != (char in delims): 
      delim_group ^= True 
      yield s[start:index] 
      start = index 
    yield s[start:index+1] 

Gdybym miał czas, bym je benchmarku xD

+0

nie trzeba wyrecytować ani tworzyć własnych kół, jeśli masz python 2.5 i więcej .. zobacz moją odpowiedź. – ghostdog74

3

Czy patrzyłeś na pyparsing? Przykład zapożyczone z the pyparsing wiki:

>>> from pyparsing import Word, alphas 
>>> greet = Word(alphas) + "," + Word(alphas) + "!" 
>>> hello1 = 'Hello, World!' 
>>> hello2 = 'Greetings, Earthlings!' 
>>> for hello in hello1, hello2: 
...  print (u'%s \u2192 %r' % (hello, greet.parseString(hello))).encode('utf-8') 
... 
Hello, World! → (['Hello', ',', 'World', '!'], {}) 
Greetings, Earthlings! → (['Greetings', ',', 'Earthlings', '!'], {}) 
Powiązane problemy