2012-06-19 11 views
10

Oto mój problem: w zmiennej, która jest tekstem i zawiera przecinki, staram się usuwać tylko przecinki znajdujące się między dwoma ciągami znaków (w rzeczywistości [ i ]). Na przykład stosując następujący ciąg:Zastąp ciąg znajdujący się między

input = "The sun shines, that's fine [not, for, everyone] and if it rains, it Will Be better." 
output = "The sun shines, that's fine [not for everyone] and if it rains, it Will Be better." 

wiem jak używać .replace dla całej zmiennej, ale nie mogę tego zrobić na części. Istnieją pewne tematy zbliża się na tej stronie, ale nie udało mi się wykorzystać je na moje własne pytanie, np:

+0

oczekiwane wyjście? –

Odpowiedz

15
import re 
Variable = "The sun shines, that's fine [not, for, everyone] and if it rains, it Will Be better." 
Variable1 = re.sub("\[[^]]*\]", lambda x:x.group(0).replace(',',''), Variable) 

Najpierw trzeba znaleźć części łańcucha, które muszą być zapisane (trzeba to zrobić z re.sub). Potem przepisujesz te części.

Funkcja var1 = re.sub("re", fun, var) oznacza: znajdź wszystkie podciągi w zmiennej var, które są zgodne z re; przetwarzać je za pomocą funkcji fun; zwróć wynik; wynik zostanie zapisany w zmiennej var1.

Wyrażenie regularne "[[^]] *]" oznacza: znaleźć podciągi, które zaczynają się [ (\[ w re), zawierają wszystko oprócz ] ([^]]* w re) i kończą ] (\] w RE).

Dla każdego znalezionego wystąpienia uruchom funkcję, która przekształca to wystąpienie na coś nowego. Funkcja:

lambda x: group(0).replace(',', '') 

To znaczy: mieć ciąg, który uznał (group(0)), wymienić ',' z '' usunąć , (innymi słowy) i zwraca wynik.

+0

Wielkie dzięki! I dziękuję za wyjaśnienie! – user1453786

+0

@ user1453786: z całym szacunkiem, odpowiedź @Qtax jest znacznie lepsza. Funkcjonalne 'sub' jest przydatną techniką, ale w tym przypadku jest to zdecydowanie przesada. – georg

+0

@ thg435: Nie, nie jest. Ponieważ nie zadziała, na przykład w przypadku niezbalansowanych nawiasów. Qtax sprawdza z twierdzeniem uprzedzającym, że kończy tylko część wyrażenia, a to jest złe. Proszę, spróbuj "" nie, dla, wszystkich ", a jeśli pada deszcz, to [a, c]," 'i zobaczysz to sam. Oczywiście można też dodać asercję lookbehind, ale to nie będzie już takie proste –

2

Można użyć takie wyrażenie pasuje do nich (jeśli nawiasy są zbalansowane):

,(?=[^][]*\]) 

Używane coś takiego:

re.sub(r",(?=[^][]*\])", "", str) 
+0

Podoba mi się twoja odpowiedź, jest bardzo czysta i skuteczna, ale myślę, że ma jedną wadę. Myślę, że to nie zadziała dla niezbilansowanych nawiasów. Sprawdzasz tylko końcową część wyrażenia. Naprawdę super byłoby rozwiązać to zadanie za pomocą twierdzeń o uprzedzeniu/patrzeniu, ale nie jestem pewien, czy to będzie tak eleganckie jak teraz. –

-2

Jeśli nie masz ochoty uczyć się wyrażeń regularnych (zobacz inne odpowiedzi na tej stronie), możesz użyć polecenia partition.

sentence = "the quick, brown [fox, jumped , over] the lazy dog" 
left, bracket, rest = sentence.partition("[") 
block, bracket, right = rest.partition("]") 

„blok” jest obecnie częścią łańcucha w nawiasach, „lewo” jest to, co było po lewej stronie uchwytu otwierającego i „prawo” to co było do prawego wspornika otwarcia.

Następnie można odzyskać pełną zdanie z:

new_sentence = left + "[" + block.replace(",","") + "]" + right 
print new_sentence # the quick, brown [fox jumped over] the lazy dog 

Jeśli masz więcej niż jeden blok, można umieścić to wszystko w pętli for, stosując polecenie partycji na „prawo” na każdym kroku.

Albo możesz uczyć się wyrażeń regularnych! Warto na dłuższą metę.

+0

Ta metoda nie zadziała, jeśli w łańcuchu będzie więcej niż jedna sekcja "specjalna" (np. "A, b [c, d] e , f [g, e] h, i "') –

+0

Nie wywołuj zmiennych 'string'; to dezorientuje deweloperów, którzy oczekują, że będzie to moduł 'string' (http://docs.python.org/library/string.html) z python stdlib. –

+0

Również, dlaczego nie używać '.split ('[', 1)' tutaj, i tak rzucasz nawiasami. Drugie wywołanie '.partition' powinno być na' reszta', a nie na 'string', więc ten kod nie będzie działał w ogóle. 'string' kończy się jako' "szybki, brązowy [szybki brązowy [lis przeskoczył] leniwego psa". –

0

Oto metoda bez regex. Można zamienić ograniczniki [] na: [/ i /], a następnie split na ograniczniku 012. Następnie każdy odd ciąg podzielonego na liście musi być przetwarzane dla comma usuwania, które mogą być wykonane podczas odbudowy ciąg w listowego:

>>> Variable = "The sun shines, that's fine [not, for, everyone] and if it rains, 
       it Will Be better." 
>>> chunks = Variable.replace('[','[/').replace(']','/]').split('/') 
>>> ''.join(sen.replace(',','') if i%2 else sen for i, sen in enumerate(chunks)) 
"The sun shines, that's fine [not for everyone] and if it rains, it Will Be 
better." 
+0

Dziękuję, ja też spróbuję. – user1453786

Powiązane problemy