2016-12-03 5 views
1

I definiertunerwartete re.sub Verhalten

s='f(x) has an occ of x but no y' 
def italicize_math(line): 
    p="(\W|^)(x|y|z|f|g|h)(\W|$)" 
    repl=r"\1<i>\2</i>\3" 
    return re.sub(p,repl,line) 

und machte den folgenden Aufruf:

print(italicize_math(s) 

Das Ergebnis ist

'<i>f</i>(x) has an occ of <i>x</i> but no <i>y</i>' 

, die nicht das, was ich erwartet hatte. Ich wollte diese statt:

'<i>f</i>(<i>x</i>) has an occ of <i>x</i> but no <i>y</i>' 

Kann mir jemand sagen, warum das erste Auftreten von x wurde nicht in dem „i“ -Tags eingeschlossen in?

+0

Die Lösungen Ich habe ziemlich gut waren, aber jetzt merke ich, ich etwas stärker als Wortgrenzen müssen, wie \ b gewährt nicht einschränkend genug. Ich möchte 4x in 4 x umgewandelt werden. Mit anderen Worten, das Vorhandensein von 4 neben x sollte eine Grenze sein. Ich werde Lookahead Assertions betrachten. – user1741137

+0

Dank der unten stehenden Hinweise habe ich herausgefunden, dass p = '(? \ 1 "Entsprach meinen Bedürfnissen – user1741137

Antwort

4

Sie scheinen zu versuchen, nicht-alphanumerischen Zeichen (\W) anpassen, wenn Sie wirklich eine Wortgrenze wollen (\b):

>>> p=r"(\b)(x|y|z|f|g|h)(\b)" 
>>> re.sub(p,repl,s) 
'<i>f</i>(<i>x</i>) has an occ of <i>x</i> but no <i>y</i>' 

Natürlich (ist nicht alphanumerische - Die Grund dafür, dass dein innerer Inhalt nicht übereinstimmt, ist, dass \W einen Charakter im Match verbraucht. also mit einer Zeichenfolge wie 'f(x)', passen Sie die (, wenn Sie f übereinstimmen. Da ( bereits zugeordnet wurde, stimmt es nicht mit wieder überein, wenn Sie versuchen, x zu entsprechen. Im Gegensatz dazu verbrauchen Wortgrenzen keine Zeichen.

3

Da das Gruppenkonstrukt die Position am Anfang der Zeichenfolge zuerst und x die vorherige Übereinstimmung überlappen würde. Außerdem sind die erste und die dritte Gruppe redundant, da sie durch Wortgrenzen ersetzt werden können; und Sie können eine Zeichenklasse verwenden, um Buchstaben zu kombinieren.

p = r'\b([fghxyz])\b' 
repl = r'<i>\1</i>' 
1

Wie frühere Antwort erwähnt, seine weil die ( char Wesen verbrauchen, wenn f somit verursachen nachfolgende passende x das Spiel zum Scheitern verurteilt.

neben ersetzen mit Wortgrenze \b, könnten Sie auch Lookahead Regex verwenden, die nur einen Blick und keine konsumieren nichts im Lookahead konsumieren. Da es nichts zu konsumieren haben, brauchen Sie nicht die \3 entweder

p=r"(\W|^)(x|y|z|f|g|h)(?=\W|$)" 
repl=r"\1<i>\2</i>" 
re.sub(p,repl,line)