2011-01-07 7 views
13

Supponiamo che io ho una stringa con un sacco di roba casuale in esso come il seguente:Python trovare sottostringa tra alcuni personaggi utilizzando espressioni regolari e sostituire()

strJunk ="asdf2adsf29Value=five&lakl23ljk43asdldl" 

E sono interessati ad ottenere la sottostringa seduto tra ' Valore = 'e' & ', che in questo esempio sarebbe' cinque '.

posso usare una regex come la seguente:

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

Come mai match.group (0) è il tutto 'Valore = cinque' e di gruppo (1) è solo 'cinque'? E c'è un modo per me di ottenere "cinque" come unico risultato? (Questa domanda nasce da me solo avendo una conoscenza tenue regex)

Ho anche intenzione di avere effettua una sostituzione in questa stringa, quali ad esempio il seguente:

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

che produce:

'asdf2adsf29Value=six&lakl23ljk43asdldl' 

Considerando che ho intenzione di eseguire le due attività sopra descritte (trovando la stringa tra "Valore =" e "&", oltre a sostituire quel valore), mi chiedevo se ci sono altri modi più efficienti di cercare la sottostringa e sostituendolo nella stringa originale. Sto bene con quello che ho, ma voglio solo assicurarmi di non occupare più tempo di quello che devo essere se ci sono metodi migliori.

risposta

9

I gruppi con nome rendono più facile ottenere il contenuto del gruppo in seguito. Compilare la tua espressione regolare una volta, e quindi riutilizzare l'oggetto compilato, sarà molto più efficiente della ricompilazione per ogni utilizzo (che è ciò che accade quando chiami ripetutamente re.search). È possibile utilizzare asserzioni positive di lookbehind e lookahead per rendere questa regex adatta alla sostituzione che si desidera eseguire.

>>> 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

La risposta di Mahmoud Abelkader funzionerà anche - purché sia ​​garantito che "=" e "&" non compariranno da nessun'altra parte in strJunk. –

2

Non sono esattamente sicuro se stai analizzando gli URL, nel qual caso, dovresti utilizzare il modulo urlparse.

Tuttavia, dato che questa non è la tua domanda, la possibilità di dividere su più campi utilizzando le espressioni regolari è estremamente veloce in Python, così si dovrebbe essere in grado di fare ciò che si vuole come segue:

import re 

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

Spero che questo ti aiuti!

EDIT:

Se si dividerà più volte, è possibile utilizzare re.compile() per compilare l'espressione regolare. Quindi avrai:

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

Come mai match.group (0) è il tutto 'Valore = cinque' e di gruppo (1) è solo 'cinque'? E c'è un modo per me di ottenere "cinque" come unico risultato? (Questa domanda deriva da me che ho solo una tenue comprensione della regex)

Ho pensato che guardare dietro l'asserzione può aiutarti qui.

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

ma è possibile fornire solo una stringa di lunghezza costante nell'aspetto dietro l'asserzione.

>>> 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 

Non riesco a trovare un modo per farlo senza regex. Il tuo modo di farlo dovrebbe essere più veloce di guardare dietro l'asserzione.

Problemi correlati