2016-07-25 20 views
1

Lange Zeit/erste Zeit.Regex Ersatz für Streifen()

Ich bin ein Apotheker von Beruf durch die Bewegungen des Unterrichtens selbst, wie man in einer Vielzahl von Sprachen, die mir für Dinge wie Aufgabenautomatisierung bei der Arbeit, aber hauptsächlich Python 3.x nützlich sind. Ich arbeite durch das eBook und finde es großartig.

Ich versuche eine der Übungsfragen aus Kapitel 7 zu vervollständigen: "Schreiben Sie eine Funktion, die eine Zeichenkette nimmt und dasselbe wie die strip() - Zeichenkette tut. Wenn keine anderen Argumente als die übergeben werden string to strip, Leerzeichen am Anfang und am Ende der Zeichenfolge werden entfernt. Andernfalls werden die im zweiten Argument der Funktion angegebenen Zeichen aus der Zeichenfolge entfernt. "

Ich bin für die Situation fest, wenn die Zeichen, die ich entfernen möchte, in der Zeichenfolge angezeigt werden möchte ich sie aus z. 'Ssstestsss'.strip (n)

#!python3 
import re 

respecchar = ['?', '*', '+', '{', '}', '.', '\\', '^', '$', '[', ']'] 


def regexstrip(string, _strip): 
    if _strip == '' or _strip == ' ': 
     _strip = r'\s' 
    elif _strip in respecchar: 
     _strip = r'\'+_strip' 
    print(_strip) #just for troubleshooting 
    re_strip = re.compile('^'+_strip+'*(.+)'+_strip+'*$') 
    print(re_strip) #just for troubleshooting 
    mstring = re_strip.search(string) 
    print(mstring) #just for troubleshooting 
    stripped = mstring.group(1) 
    print(stripped) 

Wie es gezeigt wird, ist es auf läuft (' ssstestsss', 's') nachgeben 'testsss' wie. + Bekommt alles davon und das * läßt es Ignoriere das letzte 'sss'. Wenn ich das finale * zu a + ändere, verbessert es sich nur ein bisschen, um 'testss' zu ergeben. Wenn ich die Erfassungsgruppe nicht gierig mache (dh (. +)?) Bekomme ich immer noch 'testsss' und wenn ich das Zeichen aus der Zeichenklasse für die Erfassungsgruppe ausschließe, entferne den Endstring-Anker (zB re.compile('^'+_strip+'*([^'+_strip+'.]+)'+_strip+'*') Ich bekomme ich ‚te‘ und wenn nicht das Ende String Anker entfernen sie dann es offensichtlich Fehler.

Apologies für die ausführliche und schwafeln-y Frage.

ich den gesamten Code absichtlich enthalten (in Arbeit), wie ich Ich lerne nur, also merke ich, dass mein Code wahrscheinlich ziemlich ineffizient ist, wenn Sie also andere Bereiche sehen, in denen ich meinen Code verbessern kann, lassen Sie es mich wissen Ich weiß, dass es für diesen Code keine praktische Anwendung gibt, aber ich bin es Durchgehen als Lernübung.

Ich hoffe, ich habe diese Frage angemessen gestellt und bei meinen Recherchen nichts verpasst.

Grüße

Lobsta

+0

Sie haben für die ausgeblendeten Symbole keine Zeichenklasse verwendet. Außerdem solltest du 're.escape' verwenden, um spezielle Zeichen zu vermeiden. –

+3

'(. +)?' Ist nicht dasselbe wie '(. +?)'. – Blckknght

Antwort

3

Sie (.+) ist gierig, (Standardeinstellung). ändern Sie es einfach nicht gierig, von (.+?)
verwenden, können Sie Python Regex Test bei this site

edit: Als jemand kommentierte (.+?) und (.+)? das gleiche tun, nicht tun: (.+?) ist die nicht gierig Version von (.+) während (.+)? Streichhölzer oder nicht die gierigen (.+)

+0

Oh mein ... so ein Anfänger Fehler. Was meinen Rookie-Status angeht ... macht es nur einen Fehler? Sobald ich den falsch platzierten Lazy Modifier korrigiert hatte, funktionierte es. – Lobsta

2

Wie ich in meinem Kommentar erwähnt, haben Sie keine speziellen Zeichen in die Zeichenklasse enthalten.

Auch der .* ohne re.S/re.DOTALL Modifikator stimmt nicht mit Zeilenvorschüben überein. Sie können vermeiden, es mit ^PATTERN|PATTERN$ oder \APATTERN|PATTERN\Z (beachten Sie, dass \A entspricht der Beginn einer Zeichenfolge und \Z entspricht das Ende der Zeichenfolge, $ kann vor dem endgültigen Newline-Symbol in einer Zeichenfolge übereinstimmen, und daher können Sie nicht verwenden $) .

Ich würde vorschlagen, um Ihren Code zu

import re 

def regexstrip(string, _strip=None): 
    _strip = r"\A[\s{0}]+|[\s{0}]+\Z".format(re.escape(_strip)) if _strip else r"\A\s+|\s+\Z" 
    print(_strip) #just for troubleshooting 
    return re.sub(_strip, '', string) 

print(regexstrip(" ([no more stripping'] ) ", "()[]'")) 
# \A[\s\ \(\)\[\]\']+|[\s\ \(\)\[\]\']+\Z 
# no more stripping 
print(regexstrip(" ([no more stripping'] ) ")) 
# \A\s+|\s+\Z 
# ([no more stripping'] ) 

Siehe Python demo

Hinweis schrumpfen, dass:

  • Das _strip Argument mit einem =None
  • Die _strip = r"\A[\s{0}]+|[\s{0}]+\Z".format(re.escape(_strip)) if _strip else r"\A\s+|\s+\Z" inits die optional ist Regex-Muster: Wenn _strip übergeben wird, wird die Symb ols werden in eine [...] Zeichenklasse eingefügt und escape (da wir die Symbolpositionen nicht viel kontrollieren können, ist es der schnellste und einfachste Weg, sie alle als wörtliche Symbole zu behandeln).
  • Mit re.sub entfernen wir die übereinstimmenden Teilstrings.
+0

Ich wünschte, ich könnte beide Antworten als richtig markieren. Ihre Antwort war ebenso großartig, zeigte mir eine andere (effizientere) Herangehensweise an mein Problem und half mir mit dem nächsten Teil dessen, in was ich die Funktion erweitern würde. Und lehrte mich auch einige Python-Dinge, die ATBS noch nicht hatte. – Lobsta

+0

@Lobsta Wenn du * eine * Zeichenkette * von einigen Zeichen * strippen willst, würde die Antwort von HolyDanna nicht funktionieren, wenn es einen Zeilenumbruch in der Zeichenkette gäbe. Bitte überdenken Sie den akzeptierten Status. Die ganze Idee, '. *?' Zu verwenden, ist fehlerhaft: Es prüft * jedes * Symbol auf seinem Weg vom Anfang bis zum Ende, und das ist ein riesiger Overhead. –