Jak zignorować białe znaki w ciągu tematu wyrażenia regularnego?

107

Czy istnieje prosty sposób na zignorowanie białych znaków w ciągu docelowym podczas wyszukiwania dopasowań przy użyciu wzorca wyrażenia regularnego? Na przykład, jeśli szukam frazy „koty”, chciałbym, aby pasowały słowa „c ats” lub „ca ts”. Nie mogę wcześniej usunąć białych znaków, ponieważ muszę znaleźć indeks początkowy i końcowy dopasowania (w tym wszelkie białe znaki), aby podświetlić to dopasowanie, a wszelkie spacje muszą tam być do celów formatowania.

Steven
źródło

Odpowiedzi:

124

Możesz wstawić opcjonalne białe znaki \s*między każdym innym znakiem w swoim wyrażeniu regularnym. Chociaż przyznano, będzie trochę długie.

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

Sam Dufel
źródło
Dzięki, brzmi, jakby to był właściwy kierunek. Ale właśnie zdałem sobie sprawę, że chcę tylko opcjonalnych białych znaków, jeśli następują po nowej linii. Na przykład „c \ n ats” lub „ca \ n ts” powinny być zgodne. Ale nie chciałbym, aby „c ats” pasowało, gdyby nie było nowej linii. Jakieś pomysły, jak można to zrobić?
Steven
@Steven, zobacz jak to zrobiłem poniżej, możesz łatwo dostosować moje rozwiązanie do takich konkretnych przypadków.
Bob
@chris Myślę, że to wyrażenie regularne jest tak surowe tylko dla kotów, może też zawierać dowolne wyszukiwanie liter, takich jak ten: ^([a-z]\s*)+$
Sandeep Kaur,
9

Uwzględniając komentarz Stevena do odpowiedzi Sama Dufela

Dzięki, brzmi, jakby to był właściwy kierunek. Ale właśnie zdałem sobie sprawę, że chcę tylko opcjonalnych białych znaków, jeśli następują po nowej linii. Na przykład „c \ n ats” lub „ca \ n ts” powinny być zgodne. Ale nie chciałbym, aby „c ats” pasowało, gdyby nie było nowej linii. Jakieś pomysły, jak można to zrobić?

To powinno załatwić sprawę:

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

Zobacz tę stronę, aby zobaczyć wszystkie różne odmiany „kotów”, do których pasuje.

Możesz również rozwiązać ten problem za pomocą warunkowych , ale nie są one obsługiwane w javascriptowym stylu wyrażenia regularnego.

Aurimas
źródło
3
Tak bardzo brzydki. Musi być lepszy sposób.
james.garriss
Możesz uczynić go bardziej czytelnym w składni JS (chociaż ta technika działałaby w innych językach) z:new RegExp('cats'.split('').join('(?:\n\s*)?'))
brianary
7

Chociaż zaakceptowana odpowiedź jest technicznie poprawna, bardziej praktycznym podejściem jest, jeśli to możliwe, po prostu usunięcie białych znaków zarówno z wyrażenia regularnego, jak i ciągu wyszukiwania.

Jeśli chcesz wyszukać „moje koty”, zamiast:

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

Po prostu zrób:

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

Ostrzeżenie: nie można zautomatyzować tego w wyrażeniu regularnym, zastępując wszystkie spacje pustymi ciągami, ponieważ mogą one wystąpić w negacji lub w inny sposób spowodować, że wyrażenie regularne będzie nieprawidłowe.

Konrad Höffner
źródło
5

Możesz wstawić \s*pomiędzy każdy znak w ciągu wyszukiwania, więc jeśli szukasz kota, którego użyjeszc\s*a\s*t\s*s\s*s

Jest długi, ale oczywiście możesz zbudować strunę dynamicznie.

Możesz zobaczyć, jak działa tutaj: http://www.rubular.com/r/zzWwvppSpE

Kludge
źródło
3

Jeśli chcesz zezwolić tylko na spacje, to

\bc *a *t *s\b

powinien to zrobić. Aby zezwolić także na karty, użyj

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

Usuń \bkotwice, jeśli chcesz znaleźć również catssłowa takie jak bobcatslub catsup.

Tim Pietzcker
źródło
1

To podejście można wykorzystać do automatyzacji tego (poniższe przykładowe rozwiązanie jest w Pythonie, chociaż oczywiście można je przeportować na dowolny język):

możesz wcześniej usunąć białe znaki ORAZ zapisać pozycje znaków niebędących białymi znakami, aby móc ich później użyć, aby znaleźć dopasowane pozycje brzegowe w oryginalnym ciągu, jak poniżej:

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'

Jeśli chcesz pójść dalej, możesz skonstruować obiekt dopasowania i zamiast tego go zwrócić, więc użycie tego pomocnika będzie wygodniejsze.

Wydajność tej funkcji można oczywiście również zoptymalizować, ten przykład służy tylko do pokazania ścieżki do rozwiązania.

Pion
źródło