Regex для всех строк, не содержащих строку?

Хорошо, так что это нечто совершенно глупое, но это то, что я просто никогда не научился делать и его хлопот.

Как указать строку, которая не содержит последовательность других символов. Например, я хочу совместить все строки, которые НЕ заканчиваются на .config

Я бы подумал, что могу просто сделать

.*[^(\.config)]$

но это не работает (почему бы и нет?)

Я знаю, что могу сделать

.*[^\.][^c][^o][^n][^f][^i][^g]$

но, пожалуйста, пожалуйста, скажите мне, что есть лучший способ

Ответ 1

Вы можете использовать negative lookbehind, например:

.*(?<!\.config)$

Это соответствует всем строкам, кроме тех, которые заканчиваются на ".config"

Ответ 2

В вашем вопросе есть два вопроса, так что вот несколько ответов.

Сопоставьте строки, которые не содержат определенную строку (скажем .config):

^(?:(?!\.config).)*$\r?\n?

Сопоставьте строки, которые не заканчиваются в определенной строке:

^.*(?<!\.config)$\r?\n?

и, в качестве бонуса: сопоставить строки, которые не начинаются с определенной строки:

^(?!\.config).*$\r?\n?

(каждый раз, включая символы новой строки, если они есть.

О, и ответить, почему ваша версия не работает: [^abc] означает "любой (1) символ, кроме a, b или c". Ваше другое решение также потерпит неудачу на test.hg (потому что оно также заканчивается буквой g - ваше регулярное выражение смотрит на каждый символ отдельно, а не на целую строку .config. Поэтому вам нужно lookaround, чтобы справиться с этим.

Ответ 3

(?<!\.config)$

:)

Ответ 4

Если вы не "grepping"... так как вы не используете результат совпадения, почему бы не искать строки, которые заканчиваются на .config и пропустить их? В Python:

import re
isConfig = re.compile('\.config$')
# List lst is given
filteredList = [f.strip() for f in lst if not isConfig.match(f.strip())]

Я подозреваю, что это будет работать быстрее, чем более сложное re.

Ответ 5

Используя конструкцию [^], вы создали отрицательный класс символов, который соответствует всем символам, кроме тех, которые вы назвали. Порядок символов в совпадении кандидатов не имеет значения, так что это не сработает ни на одной строке, которая имеет любой из [(\.config) (или [)gi.\onc(])

Используйте отрицательный lookahead (с регулярными выражениями perl) следующим образом: (?!\.config$). Это будет соответствовать всем строкам, которые не соответствуют буквальному ".config"

Ответ 6

Как вы просили "лучшего способа": я бы попробовал "фильтр". Я думаю, что читать и понимать очень легко:

#!/usr/bin/perl

while(<>) {
    next if /\.config$/; # ignore the line if it ends with ".config"
    print;
}

Как вы можете видеть, я использовал пример кода perl. Но я думаю, вы поняли эту идею?

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

    next if /\.config$/; # ignore the line if it ends with ".config"
    next if /\.ini$/;    # ignore the line if it ends with ".ini"
    next if /\.reg$/;    # ignore the line if it ends with ".reg"

    # now we have filtered out all the lines we want to skip
    ... process only the lines we want to use ...

Ответ 7

Я использовал Regexpal, прежде чем найти эту страницу, и придумал следующее решение, когда я хотел проверить, что строка не содержит расширение файла:

^(.(?!\.[a-zA-Z0-9]{3,}))*$ Я использовал флажок m, чтобы я мог представить много строк и посмотреть, какие из них выполнялись или не совпадали.

чтобы найти строку, которая не содержит другого выражения "^(.(?!" +, которое вы не хотите + "))*$"

Моя статья об использовании этого конкретного регулярного выражения