Регулярное выражение для строки, не заканчивающейся данным суффиксом
Я не смог найти правильное регулярное выражение, чтобы соответствовать любой строке, не заканчивающейся каким-либо условием. Например, я не хочу сопоставлять что-либо, заканчивающееся a
,
Это соответствует
b
ab
1
Это не совпадает
a
ba
Я знаю, что регулярное выражение должно заканчиваться $
чтобы отметить конец, хотя я не знаю, что должно предшествовать этому.
Изменить: Оригинальный вопрос, кажется, не является законным примером для моего случая. Итак: как обрабатывать более одного персонажа? Скажи что-нибудь не заканчивается ab
?
Я смог это исправить, используя эту тему:
.*(?:(?!ab).).$
Хотя недостатком этого является то, что он не соответствует строке из одного символа.
8 ответов
Вы не предоставляете нам язык, но если ваша поддержка регулярных выражений поддерживает утверждение, это то, что вам нужно:
.*(?<!a)$
(?<!a)
является отрицательным утверждением с задним взглядом, которое гарантирует, что до конца строки (или строки с m
модификатор), здесь нет символа "а".
Смотрите это здесь на Regexr
Вы также можете легко расширить это с другими символами, так как это проверка строки и не является классом символов.
.*(?<!ab)$
Это будет соответствовать всему, что не заканчивается на "ab", смотрите это на Regexr
Использовать не (^
) условное обозначение:
.*[^a]$
Если вы положите ^
Символ в начале скобок означает "все, кроме вещей в скобках". $
это просто якорь до конца.
Для нескольких символов просто поместите их все в их собственный набор символов:
.*[^a][^b]$
Для поиска файлов, не заканчивающихся на ".tmp", мы используем следующее регулярное выражение:
^(?!.*[.]tmp$).*$
Протестировано с Regex Tester дает следующий результат:
.*[^a]$
приведенное выше регулярное выражение будет соответствовать строкам, которые не заканчиваются a
,
Попробуй это
/.*[^a]$/
[]
обозначает класс персонажа, а ^
инвертирует класс персонажа, чтобы соответствовать всему, кроме a
,
Принятый ответ хорошо, если вы можете использовать lookarounds. Однако есть и другой подход к решению этой проблемы.
Если мы посмотрим на широко предложенное регулярное выражение для этого вопроса:
.*[^a]$
Мы обнаружим, что это почти работает. Он не принимает пустую строку, что может быть немного неудобно. Тем не менее, это незначительная проблема при работе только с одним персонажем. Однако, если мы хотим исключить всю строку, например, "abc", то:
.*[^a][^b][^c]$
не буду делать Например, он не примет переменную.
Хотя есть простое решение этой проблемы. Мы можем просто сказать:
.{,2}$|.*[^a][^b][^c]$
или более обобщенная версия:
.{,n-1}$|.*[^firstchar][^secondchar]$
где n - длина строки, которую вы хотите запретить (для abc
это 3) и firstchar
, secondchar
,... первые, вторые... n-ые символы вашей строки (для abc
это было бы a
, затем b
, затем c
).
Это вытекает из простого наблюдения, что строка, которая короче, чем текст, который мы не запрещаем, не может содержать этот текст по определению. Таким образом, мы можем либо принять что-нибудь более короткое ("ab" не "abc"), либо что-нибудь достаточно длинное, чтобы мы могли это принять, но без окончания.
Вот пример поиска, который удалит все файлы, которые не являются.jpg:
find . -regex '.{,3}$|.*[^.][^j][^p][^g]$' -delete
Вопрос старый, но я не смог найти лучшего решения, которое я разместил здесь. Найдите все USB-накопители, но не перечислите разделы, удалив, таким образом, "part[0-9]" из результатов. В итоге я сделал два grep, последний сводит на нет результат:
ls -1 /dev/disk/by-path/* | grep -P "\-usb\-" | grep -vE "part[0-9]*$"
Это приводит к моей системе:
pci-0000:00:0b.0-usb-0:1:1.0-scsi-0:0:0:0
Если бы я только хотел разделы, которые я мог бы сделать:
ls -1 /dev/disk/by-path/* | grep -P "\-usb\-" | grep -E "part[0-9]*$"
Где я получаю:
pci-0000:00:0b.0-usb-0:1:1.0-scsi-0:0:0:0-part1
pci-0000:00:0b.0-usb-0:1:1.0-scsi-0:0:0:0-part2
И когда я делаю:
readlink -f /dev/disk/by-path/pci-0000:00:0b.0-usb-0:1:1.0-scsi-0:0:0:0
Я получил:
/dev/sdb
Все, что соответствует чему-то, заканчивающемуся --- .*a$
Поэтому, когда вы соответствуете регулярному выражению, отрицаете условие или вы также можете сделать .*[^a]$
где [^a]
означает все, что not a
Если вы используете grep
или же sed
синтаксис будет немного другим. Обратите внимание, что последовательный [^a][^b]
метод не работает здесь:
balter@spectre3:~$ printf 'jd8a\n8$fb\nq(c\n'
jd8a
8$fb
q(c
balter@spectre3:~$ printf 'jd8a\n8$fb\nq(c\n' | grep ".*[^a]$"
8$fb
q(c
balter@spectre3:~$ printf 'jd8a\n8$fb\nq(c\n' | grep ".*[^b]$"
jd8a
q(c
balter@spectre3:~$ printf 'jd8a\n8$fb\nq(c\n' | grep ".*[^c]$"
jd8a
8$fb
balter@spectre3:~$ printf 'jd8a\n8$fb\nq(c\n' | grep ".*[^a][^b]$"
jd8a
q(c
balter@spectre3:~$ printf 'jd8a\n8$fb\nq(c\n' | grep ".*[^a][^c]$"
jd8a
8$fb
balter@spectre3:~$ printf 'jd8a\n8$fb\nq(c\n' | grep ".*[^a^b]$"
q(c
balter@spectre3:~$ printf 'jd8a\n8$fb\nq(c\n' | grep ".*[^a^c]$"
8$fb
balter@spectre3:~$ printf 'jd8a\n8$fb\nq(c\n' | grep ".*[^b^c]$"
jd8a
balter@spectre3:~$ printf 'jd8a\n8$fb\nq(c\n' | grep ".*[^b^c^a]$"
FWIW, я нахожу те же результаты в Regex101, который я думаю, это синтаксис JavaScript.
Плохо: https://regex101.com/r/MJGAmX/2
Хорошо: https://regex101.com/r/LzrIBu/2