2011-01-07 8 views
13

Załóżmy, że mam ciąg z dużą ilością losowej rzeczy w nim tak:Python znalezienie podciąg między niektórymi postaciami za pomocą wyrażenia regularnego i zastąpić()

strJunk ="asdf2adsf29Value=five&lakl23ljk43asdldl" 

I jestem zainteresowany w uzyskaniu podciąg siedzi między ' Wartość = "i" & ", która w tym przykładzie miałaby wartość" pięć ".

mogę używać regex jak poniżej:

match = re.search(r'Value=?([^&>]+)', strJunk) 
>>> print match.group(0) 
Value=five 
>>> print match.group(1) 
five 

Dlaczego match.group (0) jest cała sprawa 'Value = pięć' i grupa (1) jest tylko 'pięć'? I czy istnieje sposób, aby uzyskać tylko "pięć" jako jedyny rezultat? (To pytanie wynika z mi tylko o wątpliwy zrozumienie regex)

Jestem również będzie musiał dokonać zmiany w tym ciąg takich takich jak:

val1 = match.group(1) 
strJunk.replace(val1, "six", 1)  

co daje:

'asdf2adsf29Value=six&lakl23ljk43asdldl' 

Biorąc pod uwagę, że planuję wykonanie powyższych dwóch zadań (znalezienie ciągu znaków między "Wartość =" i "&", a także zastąpienie tej wartości) w kółko, zastanawiałem się, czy istnieją inne, bardziej skuteczne sposoby szukania podciągu i zastąpienie go oryginalnym ciągiem znaków. Nie mam nic przeciwko temu, co mam, ale chcę się upewnić, że nie zajmę więcej czasu, niż będę musiał, jeśli będą lepsze metody.

Odpowiedz

9

Nazwane grupy ułatwiają później pobranie zawartości grupy. Kompilowanie twojego regexa raz, a następnie ponowne użycie skompilowanego obiektu, będzie znacznie bardziej wydajne niż rekompilacja go dla każdego użycia (co dzieje się, gdy wielokrotnie wywołujesz re.search). Możesz użyć pozytywnych asercji lookbehind i uprzedzania, aby uczynić to wyrażenie regularnym odpowiednim do zamiany, którą chcesz wykonać.

>>> value_regex = re.compile("(?<=Value=)(?P<value>.*?)(?=&)") 
>>> match = value_regex.search(strJunk) 
>>> match.group('value') 
'five' 
>>> value_regex.sub("six", strJunk) 
'asdf2adsf29Value=six&lakl23ljk43asdldl' 
+0

Odpowiedź Mahmouda Abelkadera również zadziała - o ile masz gwarancję, że "=" i "&" nie pojawią się nigdzie indziej w strJunk. –

2

Nie jestem do końca pewien, czy parsujesz adresy URL, w takim przypadku zdecydowanie powinieneś zdecydowanie używać modułu urlparse.

Biorąc jednak pod uwagę, że to nie jest kwestia, możliwość podziału na wielu polach z wykorzystaniem wyrażeń regularnych jest bardzo szybki w Pythonie, więc powinieneś być w stanie robić to, co chcesz, co następuje:

import re 

strJunk ="asdf2adsf29Value=five&lakl23ljk43asdldl" 
split_result = re.split(r'[&=]', strJunk) 
split_result[1] = 'six' 
print "{0}={1}&{2}".format(*split_result) 

Mam nadzieję że to pomoże!

EDIT:

Jeśli będzie podzielone kilka razy, można użyć re.compile() skompilować wyrażenia regularnego. Będziesz mieć:

import re 
rx_split_on_delimiters = re.compile(r'[&=]') # store this somewhere 

strJunk ="asdf2adsf29Value=five&lakl23ljk43asdldl" 
split_result = rx_split_on_delimiters.split(strJunk) 
split_result[1] = 'six' 
print "{0}={1}&{2}".format(*split_result) 
0

Jak to możliwe, że match.group (0) jest całością "Wartość = pięć", a grupa (1) to tylko "pięć"? I czy istnieje sposób, aby uzyskać tylko "pięć" jako jedyny rezultat? (To pytanie pochodzi ode mnie tylko z niewielkim zrozumieniem regex)

Pomyślałem, że to spojrzenie za stwierdzeniem może ci w tym pomóc.

>>> match = re.search(r'(?<=Value=)([^&>]+)', strJunk) 
>>> match.group(0) 
'five' 

ale można podać tylko ciąg o stałej długości w spojrzeniu za asercją.

>>> match = re.search(r'(?<=Value=?)([^&>]+)', strJunk) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/usr/lib/python2.6/re.py", line 142, in search 
    return _compile(pattern, flags).search(string) 
    File "/usr/lib/python2.6/re.py", line 245, in _compile 
    raise error, v # invalid expression 
sre_constants.error: look-behind requires fixed-width pattern 

Nie mogę zrobić tego w żaden sposób bez regex. Twój sposób robienia tego powinien być szybszy, niż szukać potwierdzenia.

Powiązane problemy