Я был разочарован попыткой придумать регулярное выражение для сопоставления строк на основе определенных имен файлов, и я надеюсь, что есть ниндзя регулярных выражений (я опущу обязательную ссылку xkcd ради времени), который может помочь.
Мне нужно сопоставить любую строку, заканчивающуюся на «.htm» или «.html», которая НЕ (отрицательное сопоставление), перед которой сразу же стоит «msg-», за которой следуют 4–16 цифр чисел или дефисов. Начало строки может быть любой длины или любого содержания.
Вот моя попытка:
(?!msg-[0-9-]{4,16})\.html?$
Однако, похоже, это не работает. Частично проблема заключается в предварительном сопоставлении - я хочу сопоставить всю строку, если она соответствует этим критериям, а не первую часть строки, которая не соответствует. Мы ценим любые предложения.
Если это важно для вкусов, это входит в сценарий bash в Debian.
РЕДАКТИРОВАТЬ:
Вот несколько строк, которые должны соответствовать регулярному выражению
the-quick-brown-fox-jumped-over-the-lazy-dog.html # ends with .html but no digits/hyphens just prior
wdihwi94uq239ujdf23yefh02msg-2-8.htm # digit/hyphen count between 'msg-' and '.html' is below 4
ohdf23890yo4c89uwmsg-999-24j345.html # non-number/hyphen in chars between 'msg-' and '.html'
Вот несколько строк, которые НЕ должны соответствовать регулярному выражению:
kh3j42he2-dwfascn233=feufefask0msg-34535-355 # does not end with '.htm'/'.html'
395-u78{efihighqwioh9msg-8455-212.html # ends with 'msg-' then 4-16 of [0-9-] then '.html'
dfhjwih9asnm)qpzmx.wod923klsj39msg-00-0000.htm
Я думаю, что следующее регулярное выражение Perl соответствует тому, что вы хотите:
(?!.*msg-[-0-9]{4,16}\.html?$).*\.html?$
Однако, AFAIK, нет места, где bash поддерживает регулярные выражения Perl. В =~
оператор поддерживает только расширенные регулярные выражения¹, которые не включают утверждения просмотра вперед нулевой ширины, такие как (?=…)
и (?!…)
.
Теоретически возможно преобразовать регулярное выражение с утверждениями, содержащими поиск, в одно без, но в результате регулярное выражение будет огромным. Гораздо проще использовать два регулярных выражения:
[[ $string =~ \.html?$ && ! $string =~ msg-[-0-9]{4,16}\.html?$ ]]
¹ Сначала были основной regexps (BRE) (с несколькими вариантами синтаксиса), затем появился расширенный регулярные выражения (ERE) с большим количеством функций (и снова несколько вариантов синтаксиса). Perl добавил еще больше возможностей, и многие языки предоставляют Perl-совместимые регулярные выражения (pcre). Но bash придерживается ERE.
попробуйте с ^(?!\w+msg-\d+.[html|htm]+).*$
Также kodos должен быть вашим другом; p (это приложение с графическим интерфейсом очень полезно, когда вы возитесь с regexpr)