Wie ignoriere ich Leerzeichen in einer Betreffzeichenfolge mit regulären Ausdrücken?

106

Gibt es eine einfache Möglichkeit, den Leerraum in einer Zielzeichenfolge bei der Suche nach Übereinstimmungen mithilfe eines Musters mit regulären Ausdrücken zu ignorieren? Wenn ich beispielsweise nach "Katzen" suche, möchte ich, dass "c ats" oder "ca ts" übereinstimmen. Ich kann das Leerzeichen nicht vorher entfernen, da ich den Anfangs- und Endindex der Übereinstimmung (einschließlich aller Leerzeichen) finden muss, um diese Übereinstimmung hervorzuheben, und jedes Leerzeichen muss für Formatierungszwecke vorhanden sein.

Steven
quelle

Antworten:

123

Sie können optionale Leerzeichen \s*zwischen alle anderen Zeichen in Ihrer Regex einfügen. Obwohl dies selbstverständlich ist, wird es etwas länger dauern.

/cats/ -> /c\s*a\s*t\s*s/

Sam Dufel
quelle
Danke, hört sich so an, als wäre das der richtige Weg. Aber ich habe gerade festgestellt, dass ich die optionalen Leerzeichen nur dann möchte, wenn sie einer neuen Zeile folgen. So sollten beispielsweise "c \ n ats" oder "ca \ n ts" übereinstimmen. Aber ich möchte nicht, dass "c ats" übereinstimmen, wenn es keine neue Zeile gibt. Irgendwelche Ideen, wie das gemacht werden könnte?
Steven
@Steven, sehen Sie, wie ich es unten gemacht habe, Sie können meine Lösung leicht an solche speziellen Fälle anpassen.
Bob
@chris Ich denke, dieser Regex ist so streng für nur Katzen, dass er auch für jede Suche nach Buchstaben wie diesen geschrieben werden kann: ^([a-z]\s*)+$
Sandeep Kaur
9

Adressierung von Stevens Kommentar zu Sam Dufels Antwort

Danke, hört sich so an, als wäre das der richtige Weg. Aber ich habe gerade festgestellt, dass ich die optionalen Leerzeichen nur dann möchte, wenn sie einer neuen Zeile folgen. So sollten beispielsweise "c \ n ats" oder "ca \ n ts" übereinstimmen. Aber ich möchte nicht, dass "c ats" übereinstimmen, wenn es keine neue Zeile gibt. Irgendwelche Ideen, wie das gemacht werden könnte?

Dies sollte den Trick tun:

/c(?:\n\s*)?a(?:\n\s*)?t(?:\n\s*)?s/

Auf dieser Seite finden Sie alle verschiedenen Variationen von 'Katzen', die dazu passen.

Sie können dies auch mithilfe von Bedingungen lösen , diese werden jedoch in der Javascript-Version von Regex nicht unterstützt.

Aurimas
quelle
3
So sehr hässlich. Es muss einen besseren Weg geben.
James.garriss
Sie könnten es in der JS-Syntax besser lesbar machen (obwohl die Technik in anderen Sprachen funktionieren würde) mit:new RegExp('cats'.split('').join('(?:\n\s*)?'))
Brian
7

Während die akzeptierte Antwort technisch korrekt ist, besteht ein praktischerer Ansatz, wenn möglich, darin, Leerzeichen sowohl aus dem regulären Ausdruck als auch aus der Suchzeichenfolge zu entfernen.

Wenn Sie nach "meinen Katzen" suchen möchten, anstatt:

myString.match(/m\s*y\s*c\s*a\*st\s*s\s*/g)

Mach einfach:

myString.replace(/\s*/g,"").match(/mycats/g)

Warnung: Sie können dies für den regulären Ausdruck nicht automatisieren, indem Sie einfach alle Leerzeichen durch leere Zeichenfolgen ersetzen, da diese in einer Negation auftreten oder Ihren regulären Ausdruck auf andere Weise ungültig machen können.

Konrad Höffner
quelle
5

Sie können \s*zwischen jedes Zeichen in Ihrer Suchzeichenfolge setzen, wenn Sie also nach einer Katze suchen, die Sie verwenden würdenc\s*a\s*t\s*s\s*s

Es ist lang, aber Sie können den String natürlich dynamisch erstellen.

Sie können es hier sehen: http://www.rubular.com/r/zzWwvppSpE

Kludge
quelle
3

Wenn Sie nur Leerzeichen zulassen möchten, dann

\bc *a *t *s\b

Sollte es tun. Verwenden Sie, um auch Registerkarten zuzulassen

\bc[ \t]*a[ \t]*t[ \t]*s\b

Entfernen Sie die \bAnker, wenn Sie auch catsin Wörtern wie bobcatsoder finden möchten catsup.

Tim Pietzcker
quelle
1

Dieser Ansatz kann verwendet werden, um dies zu automatisieren (die folgende beispielhafte Lösung ist in Python, obwohl sie offensichtlich in jede Sprache portiert werden kann):

Sie können das Leerzeichen vorher entfernen UND die Positionen von Nicht-Leerzeichen speichern, damit Sie sie später verwenden können, um die übereinstimmenden Zeichenfolgengrenzpositionen in der Originalzeichenfolge wie folgt zu ermitteln:

def regex_search_ignore_space(regex, string):
    no_spaces = ''
    char_positions = []

    for pos, char in enumerate(string):
        if re.match(r'\S', char):  # upper \S matches non-whitespace chars
            no_spaces += char
            char_positions.append(pos)

    match = re.search(regex, no_spaces)
    if not match:
        return match

    # match.start() and match.end() are indices of start and end
    # of the found string in the spaceless string
    # (as we have searched in it).
    start = char_positions[match.start()]  # in the original string
    end = char_positions[match.end()]  # in the original string
    matched_string = string[start:end]  # see

    # the match WITH spaces is returned.
    return matched_string

with_spaces = 'a li on and a cat'
print(regex_search_ignore_space('lion', with_spaces))
# prints 'li on'

Wenn Sie weiter gehen möchten, können Sie das Übereinstimmungsobjekt erstellen und stattdessen zurückgeben, sodass die Verwendung dieses Hilfsprogramms praktischer ist.

Und die Leistung dieser Funktion kann natürlich auch optimiert werden. Dieses Beispiel soll nur den Weg zu einer Lösung zeigen.

Bob
quelle