Нужно регулярное выражение, чтобы исключить определенные строки - PullRequest
8 голосов
/ 24 ноября 2008

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

somefile_1.txt
somefile_2.txt
somefile_{anything}.txt

но не совпадает:

somefile_16.txt

Я пытался

somefile_[^(16)].txt

без удачи (включая даже запись "16")

Ответы [ 6 ]

11 голосов
/ 24 ноября 2008

Некоторые библиотеки регулярных выражений допускают просмотр:

somefile(?!16\.txt$).*?\.txt

В противном случае вы все равно можете использовать несколько классов символов:

somefile([^1].|1[^6]|.|.{3,})\.txt

или, для достижения максимальной переносимости:

somefile([^1].|1[^6]|.|....*)\.txt

[^(16)] означает: соответствует любому символу, кроме фигурных скобок, 1 и 6.

5 голосов
/ 24 ноября 2008

Лучшее решение уже упоминалось:

somefile_(?!16\.txt$).*\.txt

Это работает и достаточно жадно, чтобы воспринимать все, что происходит на одной линии. Однако если вы знаете, что вам нужно правильное имя файла, я бы предложил также ограничить количество недопустимых символов:

somefile_(?!16)[^?%*:|"<>]*\.txt

Если вы работаете с движком регулярных выражений, который не поддерживает прогнозирование, вам придется подумать, как это сделать! 16. Вы можете разбить файлы на две группы: те, которые начинаются с 1, и за которыми не следует 6, и те, которые начинаются с чего-либо еще:

somefile_(1[^6]|[^1]).*\.txt

Если вы хотите разрешить somefile_16_stuff.txt, но НЕ somefile_16.txt, приведенных выше регулярных выражений недостаточно. Вам нужно будет установить свой лимит по-другому:

somefile_(16.|1[^6]|[^1]).*\.txt

Объедините все это, и вы получите две возможности, одна из которых блокирует один экземпляр (somefile_16.txt), а другая блокирует все семейства (somefile_16 * .txt). Я лично думаю, что вы предпочитаете первый:

somefile_((16[^?%*:|"<>]|1[^6?%*:|"<>]|[^1?%*:|"<>])[^?%*:|"<>]*|1)\.txt
somefile_((1[^6?%*:|"<>]|[^1?%*:|"<>])[^?%*:|"<>]*|1)\.txt

В версии без удаления специальных символов, чтобы было легче читать:

somefile_((16.|1[^6]|[^1).*|1)\.txt
somefile_((1[^6]|[^1]).*|1)\.txt
4 голосов
/ 24 ноября 2008

Чтобы строго соблюдать ваши требования и быть разборчивыми, лучше использовать:

^somefile_(?!16\.txt$).*\.txt$

так что somefile_1666.txt, который является {что угодно}, может быть сопоставлен;)

но иногда его удобнее читать ...:

ls | grep -e 'somefile_.*\.txt' | grep -v -e 'somefile_16\.txt'
3 голосов
/ 24 ноября 2008
somefile_(?!16).*\.txt

(?! 16) означает: утверждать, что невозможно сопоставить регулярное выражение "16", начиная с этой позиции.

2 голосов
/ 24 ноября 2008

Иногда просто использовать два регулярных выражения. Сначала ищите все, что вы хотите, а затем игнорируйте все, что вы не делаете. Я делаю это все время в командной строке, где я передаю регулярное выражение, которое переводит надмножество в другое регулярное выражение, которое игнорирует вещи, которые мне не нужны.

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

1 голос
/ 24 ноября 2008

без использования lookahead

somefile_(|.|[^1].+|10|11|12|13|14|15|17|18|19|.{3,}).txt

Прочитайте как: somefile_, а затем:

  1. ничего.
  2. один символ.
  3. любой один символ, кроме 1, за которым следуют любые другие символы.
  4. три или более символов.
  5. либо 10 .. 19 обратите внимание, что 16 опущено.

и, наконец, .txt.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...