Как игнорировать пробелы в строке темы регулярного выражения?

107

Есть ли простой способ игнорировать пробелы в целевой строке при поиске совпадений с использованием шаблона регулярного выражения? Например, если я ищу «кошки», я хочу, чтобы совпадали «c ats» или «ca ts». Я не могу заранее вырезать пробелы, потому что мне нужно найти начальный и конечный индекс соответствия (включая любые пробелы), чтобы выделить это совпадение, и любые пробелы должны быть там для целей форматирования.

Стивен
источник

Ответы:

124

Вы можете вставить необязательные пробельные символы \s* между всеми другими символами в регулярном выражении. Хотя это разрешено, это будет немного длинновато.

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

Сэм Дюфель
источник
Спасибо, похоже, так и надо. Но я только что понял, что мне нужны необязательные пробельные символы, только если они следуют за новой строкой. Так, например, должны совпадать "c \ n ats" или "ca \ n ts". Но не хотел бы, чтобы "c ats" совпадали, если нет новой строки. Есть идеи, как это можно сделать?
Стивен
@ Стивен, посмотрите, как я это сделал, ниже, вы легко можете адаптировать мое решение для таких конкретных случаев.
Боб
@chris Я думаю, это регулярное выражение настолько строго для кошек, что оно также может писать для любого поиска таких букв, как это: ^([a-z]\s*)+$
Сандип Каур
9

Обращаясь к комментарию Стивена к ответу Сэма Дюфеля

Спасибо, похоже, так и надо. Но я только что понял, что мне нужны необязательные пробельные символы, только если они следуют за новой строкой. Так, например, должны совпадать "c \ n ats" или "ca \ n ts". Но не хотел бы, чтобы "c ats" совпадали, если нет новой строки. Есть идеи, как это можно сделать?

Это должно помочь:

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

На этой странице вы найдете все возможные варианты слова «кошки».

Вы также можете решить эту проблему с помощью условных выражений, но они не поддерживаются в javascript-версии регулярных выражений.

Ауримас
источник
3
Очень некрасиво. Должен быть способ получше.
james.garriss
Вы можете сделать его более читабельным в синтаксисе JS (хотя этот метод будет работать и на других языках) с помощью:new RegExp('cats'.split('').join('(?:\n\s*)?'))
brianary
7

Хотя принятый ответ является технически правильным, более практичный подход, если это возможно, - просто удалить пробелы как из регулярного выражения, так и из строки поиска.

Если вы хотите искать «мои кошки» вместо:

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

Просто сделать:

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

Предупреждение: вы не можете автоматизировать это в регулярном выражении, просто заменив все пробелы пустыми строками, потому что они могут возникнуть в отрицании или иным образом сделать ваше регулярное выражение недействительным.

Конрад Хёффнер
источник
5

Вы можете поместить \s*между каждым символом в строке поиска, поэтому, если вы ищете кота, вы должны использоватьc\s*a\s*t\s*s\s*s

Это долго, но вы, конечно, можете строить строку динамически.

Вы можете увидеть, как это работает здесь: http://www.rubular.com/r/zzWwvppSpE

Kludge
источник
3

Если вы хотите разрешить только пробелы, тогда

\bc *a *t *s\b

должен это сделать. Чтобы также разрешить вкладки, используйте

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

Удалите \bякоря, если вы также хотите найти catsв таких словах, как bobcatsили catsup.

Тим Пицкер
источник
1

Этот подход можно использовать для автоматизации этого (следующее примерное решение находится на Python, хотя, очевидно, его можно портировать на любой язык):

вы можете заранее удалить пробелы и сохранить позиции непробельных символов, чтобы вы могли использовать их позже, чтобы найти совпадающие позиции границ строки в исходной строке, как показано ниже:

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'

Если вы хотите пойти дальше, вы можете создать объект соответствия и вместо этого вернуть его, так что использование этого помощника будет более удобным.

И, конечно, производительность этой функции также можно оптимизировать, этот пример просто показывает путь к решению.

Боб
источник