Problema de correspondência negativa do Regex

1

Estou frustrado tentando criar um regex para combinar strings com base em nomes de arquivos específicos e espero que haja um ninja regex (omitirei o obrigatório xkcd link por questão de tempo) por aí que pode ajudar .

Eu preciso corresponder qualquer string que termine com ".htm" ou ".html" que NÃO seja (correspondência negativa) precedida imediatamente por "msg-" seguida por 4-16 dígitos de números ou hifens. O início da string pode ter qualquer tamanho ou conteúdo.

Aqui está minha tentativa até agora:

(?!msg-[0-9-]{4,16})\.html?$

No entanto, isso não parece funcionar. Parte do problema é lookahead matching - quero corresponder a string inteira se ela atender a esses critérios, em vez da primeira parte da string que não corresponde. Qualquer sugestão seria apreciada.

Caso seja importante para sabores, isso está indo para um script bash no Debian.

EDITAR:

Aqui estão algumas sequências que devem corresponder ao regex

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'

Aqui estão algumas strings que NÃO devem corresponder ao regex:

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
    
por nedm 19.08.2010 / 22:02

2 respostas

6

Acho que o seguinte regexp Perl corresponde ao que você deseja:

(?!.*msg-[-0-9]{4,16}\.html?$).*\.html?$

No entanto AFAIK não existe nenhum lugar onde o bash suporte regexps Perl. O operador =~ suporta apenas regexps estendidos¹, que não incluem asserções lookahead de largura zero, como (?=…) e (?!…) .

É teoricamente possível converter um regexp com asserções lookahaed para um sem, mas o regexp resultante seria enorme. É muito mais simples usar dois regexps:

[[ $string =~ \.html?$ && ! $string =~ msg-[-0-9]{4,16}\.html?$ ]]

¹ Primeiro, houve basic regexps (BRE) (com diversas variantes de sintaxe), depois veio extended regexps (ERE) com mais recursos (e novamente diversas variantes de sintaxe). O Perl adicionou ainda mais recursos, e muitos idiomas fornecem expressões regulares compatíveis com Perl (pcre). Mas a bash adere a ERE.

    
por 19.08.2010 / 23:09
2

tente com ^(?!\w+msg-\d+.[html|htm]+).*$

Além disso, o kodos deve ser seu amigo; p (É uma aplicação de gui muito útil ao brincar com o regexpr)

    
por 19.08.2010 / 22:20

Tags