2013-05-30 14 views
16

Mam następujące nazwy plików, które wykazują ten wzór:Python regex podzielonego bez pusty ciąg

000014_L_20111007T084734-20111008T023142.txt 
000014_U_20111007T084734-20111008T023142.txt 
... 

chcę wyodrębnić dwie środkowe części znacznika czasu po drugim podkreślenia '_' i przed '.txt'. Użyłem więc następujący podział Python regex ciąg:

time_info = re.split('^[0-9]+_[LU]_|-|\.txt$', f) 

Ale to daje mi dwa dodatkowe puste struny w zwróconej liście:

time_info=['', '20111007T084734', '20111008T023142', ''] 

Jak mogę dostać tylko informacje skarbowej dwa czasową? to znaczy chcę:

time_info=['20111007T084734', '20111008T023142'] 

Odpowiedz

12

Nie użyj re.split(), użyj metryki groups() od obiektów regex Match/SRE_Match.

>>> f = '000014_L_20111007T084734-20111008T023142.txt' 
>>> time_info = re.search(r'[LU]_(\w+)-(\w+)\.', f).groups() 
>>> time_info 
('20111007T084734', '20111008T023142') 

Można nawet nazwać grupy przechwytywania i pobierać je w dict, chociaż użyć groupdict() zamiast groups() do tego. (Wzór regex dla takiego przypadku byłby podobny do r'[LU]_(?P<groupA>\w+)-(?P<groupB>\w+)\.')

+0

To jest dobre rozwiązanie. Dzięki. – tonga

+8

To wstyd 'split' nie ma opcji" brak pustych napisów ". – Elazar

+1

@Elazar Niezupełnie, chodzi tylko o to, w jaki sposób wdrożono 're.split()' i jaki jest jego zamierzony cel. W takich przypadkach rozsądniej jest zbudować wzór dla pożądanych danych niż zbudować taki, który pasowałby do wszystkiego, co nie jest pożądane. (Chociaż 'str.split()' faktycznie upuszcza puste ciągi, gdy separator jest nieokreślony lub 'None'.) – JAB

13

nie jestem ekspertem Python ale może można po prostu usunąć puste ciągi z listy?

time_info = re.split('^[0-9]+_[LU]_|-|\.txt$', f) 
time_info = filter(None, str_list) 
+0

To działa. Dzięki. Zastanawiam się, czy istnieje jedno rozwiązanie jednoprzebiegowe za pomocą funkcji 're.split()'. – tonga

+0

@tonga jest, ale jest mniej ładnie: 'time_info = [x dla x w re.split ('^ [0-9] + _ [LU] _ | - | \ .txt $', f) jeśli x] ' – FraggaMuffin

+0

Ponieważ filter() zwraca obiekt filtru, musisz później użyć list():' time_info = list (filter (None, str_list)) ' –

2

Jeśli znaczniki czasu są zawsze po drugim _ następnie można użyć str.split i str.strip:

>>> strs = "000014_L_20111007T084734-20111008T023142.txt" 
>>> strs.strip(".txt").split("_",2)[-1].split("-") 
['20111007T084734', '20111008T023142'] 
+0

Uwielbiam robić te rzeczy bez REs. Nie wiem dlaczego. – Elazar

+0

@Ashwini: Dzięki. To działa. Ale w jaki sposób mogę to zrobić z podziałem regex? – tonga

+0

@Elazar Podejrzewam, że wyrażenia regularne mogą być dość zagadkowe, jeśli są wykonywane nieprawidłowo lub są zbyt skomplikowane i nie zawierają komentarzy. Czasami manipulowanie ciągami za pomocą RE może być łatwiejsze do zrozumienia, gdy zostanie utworzone jako seria wywołań funkcji. (W tym przypadku jednak szereg operacji dostępu 'split()'/'strip()'/element jest bardziej restrykcyjny niż użycie RE.) – JAB

1
>>> f='000014_L_20111007T084734-20111008T023142.txt' 
>>> f[10:-4].split('-') 
['0111007T084734', '20111008T023142'] 

lub nieco bardziej ogólnie:

>>> f[f.rfind('_')+1:-4].split('-') 
['20111007T084734', '20111008T023142']