Pode parecer uma pergunta estúpida, mas tive uma longa conversa com alguns de meus colegas desenvolvedores e pareceu uma coisa divertida de se pensar.
Assim; Qual é o seu pensamento - como é um Regex, que nunca será correspondido por nenhuma string!
Edit : Por que eu quero isso? Bem, primeiro porque acho interessante pensar em uma expressão assim e, em segundo lugar, porque preciso dela para um script.
Nesse script eu defino um dicionário como Dictionary<string, Regex>
. Isso contém, como você vê, uma string e uma expressão.
Com base nesse dicionário, crio métodos que todos usam esse dicionário apenas como referência sobre como devem fazer seu trabalho, um deles corresponde às expressões regulares em um arquivo de log analisado.
Se uma expressão for correspondida, outra Dictionary<string, long>
será adicionada um valor retornado pela expressão. Portanto, para capturar quaisquer mensagens de log que não correspondam a uma expressão no dicionário, criei um novo grupo chamado "desconhecido".
A este grupo, tudo o que não corresponde a nada é adicionado. Mas, para evitar que a expressão "desconhecida" não corresponda (por acidente) a uma mensagem de log, eu tive que criar uma expressão que certamente nunca é correspondida, independentemente da string que eu fornecer.
Portanto, aí está minha razão para esta "não ser uma pergunta real" ...
fonte
Respostas:
Na verdade, isso é bastante simples,
embora dependa da implementação / flags*:Combina um caractere
a
após o final da string. Boa sorte.AVISO:
Essa expressão é cara - ela varrerá a linha inteira, localizará a âncora de fim de linha e só então não encontrará a
a
e retornará uma correspondência negativa. (Veja o comentário abaixo para mais detalhes.)* Originalmente, não pensei muito no regexp no modo multilinha, onde
$
também corresponde ao final de uma linha. Na verdade, ele corresponderia à string vazia logo antes da nova linha , para que um caractere comum comoa
nunca possa aparecer depois$
.fonte
$a
. É equivalente a Perl$(?:a)
também é muito lentoperl -Mre=debug -e'$_=a x 50; /$(?:a)/'
.timeit
epython3
.$a
corresponderá ao texto literal$a
, porque$
é inválido como uma âncora nesse padrão.Alavancagem
negative lookahead
:este ER é uma contradição em termos e, portanto, nunca corresponderá a nada.
NOTA:
No Python, re.match () adiciona implicitamente uma âncora no início da string (
\A
) ao início da expressão regular. Essa âncora é importante para o desempenho: sem ela, toda a cadeia será varrida. Aqueles que não usam Python vão querer adicionar a âncora explicitamente:fonte
(?=x)(?!x)
e assim por diante (concatenações de visões contraditórias e o mesmo para olhar para trás), e muitos deles também trabalham para valores arbitrários dex
(as necessidades de lookbehindsx
s que correspondem a cadeias de comprimento fixo).r'a\bc'
procurando um limite de palavras imediatamente cercado por letras dos dois lados (variante: caracteres não-palavras em ambos os lados).perl -Mre=debug -e'$_=x x 8; /(?!x)x/'
. Você pode torná-lo mais rápido ancorando-o no início\A(?!x)x
ou no final(?!x)x\z
.perl -Mre=debug -e'$_=x x 8; /(?!x)x\z/; /\A(?!x)x/'
Um que foi esquecido:
Não pode corresponder porque a sequência vazia não contém um limite de palavras. Testado em Python 2.5.
fonte
\`\b\'
funciona, que substitui a sintaxe do Emacs por "início / fim de texto" (em oposição a "início / fim" da linha").olhar em volta:
(?=a)b
Para iniciantes em regex: o olhar positivo à frente
(?=a)
garante que o próximo caractere sejaa
, mas não altere o local da pesquisa (ou inclua o 'a' na sequência correspondente). Agora que o próximo caractere está confirmadoa
, a parte restante do regex (b
) corresponde apenas se o próximo caractere forb
. Portanto, esse regex corresponde apenas se um caractere for ao mesmo tempoa
eb
ao mesmo tempo.fonte
a\bc
, onde\b
é uma expressão de largura zero que corresponde ao limite da palavra.Não pode aparecer no meio de uma palavra, o que forçamos.
fonte
a
no texto.$.
.^
$.^
(?!)
fonte
^
só tem significado especial como o primeiro caractere de uma regexp e$
só tem significado especial no final de uma regexp, a menos que a expressão regular seja uma expressão de várias linhas./$./
significa algo totalmente diferente. Significa corresponder ao valor atual de$.
(número da linha de entrada) . Mesmo/$(.)/
poderia corresponder a algo se você escreveuuse re '/s';
antes. (perl -E'say "\n" =~ /$(.)/s || 0'
)^
e$
são especiais apenas no início e no final (respectivamente) do padrão, portanto, nenhum$.
ou.^
ou$.^
funcionaria.(?!)
é um recurso Perl / PCRE, acredito.Correspondência máxima
Pelo menos um
a
seguido por qualquer número dea
's, sem retroceder. Em seguida, tente combinar mais uma
.ou subexpressão independente
Isso é equivalente a colocar
a+
uma subexpressão independente, seguida por outraa
.fonte
O Perl 5.10 suporta palavras de controle especiais chamadas "verbos", que são colocadas em
(*...)
seqüência. (Compare com a(?...)
sequência especial.) Entre eles, inclui o(*FAIL)
verbo que retorna da expressão regular imediatamente.Observe que os verbos também são implementados no PCRE logo depois, para que você possa usá-los em PHP ou outras linguagens usando a biblioteca PCRE também. (No entanto, você não pode em Python ou Ruby. Eles usam seu próprio mecanismo.)
fonte
\b
corresponde aos limites da palavra - a posição entre uma letra e uma não-letra (ou o limite da string).\B
é seu complemento - ele corresponde à posição entre duas letras ou entre não letras.Juntos, eles não podem corresponder a nenhuma posição.
Veja também:
fonte
^\B\b
. Nos idiomas em que "início de texto" e "início de linha" têm sintaxe diferente, convém usar a sintaxe "início de texto"; caso contrário, você estará testando todas as linhas. (por exemplo, em Emacs isso seria\`\B\b
ou"\\`\\B\\b"
.)^
é problemático em certa sintaxe do regexp (por exemplo, POSIX BRE), onde^
é apenas uma âncora quando é o primeiro caractere do padrão e corresponde a um^
caractere literal .:)
- essa é uma pergunta não prática, onde o objetivo era encontrar uma resposta interessante - e não uma resposta eficiente. Dito isso, o padrão pode ser rejeitado no tempo de liner (com o tamanho da cadeia de destino), portanto, não é ruim para uma regex - a maioria dos padrões aqui é a mesma e^
pode ser linear se não for otimizada.Isso parece funcionar:
fonte
$.
. Nesse caso, você deve recorrer$(.)
ou mais equivalente$(?:.)
.$.
corresponderá a um literal$
seguido por qualquer caractere, porque$
é inválido como uma âncora nesse padrão.Que tal
$^
ou talvez(?!)
?fonte
^
corresponde ao início e$
ao final de uma linha.(?!)
- um olhar negativo para uma corda vazia. Mas alguns tipos de expressões regulares também tratam isso como um erro de sintaxe.$^
irá corresponder esses caracteres literais, porque os personagens são inválidos como âncoras (ou seja, a razão que você usou o padrão faz com que ele não fazer o que você queria.)O mais rápido será:
'a' pode ser qualquer caractere não especial ('x', 'y'). A implementação do Knio pode ser um pouco mais pura, mas essa será mais rápida para todas as strings que não começarem com o caractere que você escolher, em vez de 'a', porque não corresponderá ao primeiro caractere, e sim ao segundo nesses casos.
fonte
^
é especial apenas como o primeiro caractere e da mesma forma com$
. Com qualquer ferramenta Unix, esse regexp corresponde a qualquer coisa que contenha a string literala^
.>^
.O Python não aceita, mas o Perl:
Essa regex deve (teoricamente) tentar corresponder a um número infinito (par) de
w
s, porque o primeiro grupo (()
s) se repete em si mesmo. O Perl parece não emitir nenhum aviso, mesmouse strict; use warnings;
assim, portanto, suponho que seja pelo menos válido, e meu (mínimo) teste não corresponde a nada, então o envio para sua crítica.fonte
perl -Mre=debug -e'"www wwww wwwww wwwwww" =~ /(w\1w)/'
[^\d\D]
ou(?=a)b
oua$a
oua^a
fonte
Isso não funcionará no Python, e em muitos outros idiomas, mas em um regex Javascript,
[]
é uma classe de caractere válida que não pode ser correspondida. Portanto, o seguinte deve falhar imediatamente, independentemente da entrada:Gosto mais do que
/$a/
porque, para mim, comunica claramente sua intenção. E quanto a quando você precisaria, eu precisava disso porque precisava de um fallback para um padrão compilado dinamicamente com base na entrada do usuário. Quando o padrão é inválido, preciso substituí-lo por um padrão que não corresponda a nada. Simplificado, fica assim:fonte
Todos os exemplos que envolvem um correspondente de limites seguem a mesma receita. Receita:
Escolha qualquer um dos correspondentes de limite: ^, $, \ b, \ A, \ Z, \ z
Faça o oposto do que eles significam
Exemplos:
^ e \ A são destinados ao início, portanto, não os use no início
\ b corresponde a um limite de palavras, portanto, use-o entre
$, \ Z e \ z são destinados ao fim, portanto, não os use no final
Outros envolvem o uso de lookahead e lookbehind, que também funcionam com a mesma analogia: se você der lookahead positivo ou negativo seguido de algo oposto
Se você der uma olhada positiva ou negativa atrás de algo oposto
O seu poderia ser mais esse padrão e mais analogias.
fonte
Tantas boas respostas!
Semelhante à resposta do @ nivk, eu gostaria de compartilhar a comparação de desempenho do Perl para diferentes variantes do regex que nunca combina.
Velocidade Regex:
Velocidade Regex:
(Ubuntu no Intel i5-3320M, kernel do Linux 4.13, Perl 5.26)
fonte
eu acredito
abrange até os casos em que a expressão regular inclui sinalizadores como MULTILINE, DOTALL etc.
Acredito (mas ainda não a comparei) que, independentemente do comprimento (> 0) da cadeia entre
\Z
e\A
, o tempo até a falha deve ser constante.fonte
ou
Com PCRE e PERL, você pode usar esse verbo de controle de retorno que força o padrão a falhar imediatamente.
fonte
Depois de ver algumas dessas ótimas respostas, o comentário de @ arantius (sobre timing
$x
vsx^
vs(?!x)x
) sobre a resposta atualmente aceita me fez querer cronometrar algumas das soluções fornecidas até agora.Usando o padrão de linha de 275k do @ arantius, executei os seguintes testes no Python (v3.5.2, IPython 6.2.1).
TL; DR:
'x^'
e'x\by'
são os mais rápidos por um fator de pelo menos ~ 16, e ao contrário da descoberta de @ arantius,(?!x)x
estava entre os mais lentos (~ 37 vezes mais lento). Portanto, a questão da velocidade certamente depende da implementação. Teste você mesmo no sistema pretendido antes de confirmar se a velocidade é importante para você.ATUALIZAÇÃO: Aparentemente, há uma grande discrepância entre tempo
'x^'
e tempo'a^'
. Consulte esta pergunta para obter mais informações e a edição anterior para tempos mais lentos com ema
vez dex
.A primeira vez que executei isso, esqueci de
r
exibir as três últimas expressões, então'\b'
fui interpretada como'\x08'
o caractere de backspace. No entanto, para minha surpresa,'a\x08c'
foi mais rápido que o resultado mais rápido anterior! Para ser justo, ele ainda corresponderá a esse texto, mas achei que ainda valia a pena notar, porque não sei por que é mais rápido.Meu arquivo de teste foi criado usando uma fórmula para "... Conteúdo legível e sem linhas duplicadas" (no Ubuntu 16.04):
fonte
\B\b
é terrivelmente falho em termos de desempenho (como todo padrão que não está ancorado em uma posição, mas esse padrão é particularmente ruim). Tente comparações^\B\b
.Regex vazio
A melhor regex para nunca corresponder a nada é uma regex vazia. Mas não tenho certeza de que todos os mecanismos de regex aceitem isso.
Regex impossível
A outra solução é criar uma regex impossível. Descobri que são
$-^
necessárias apenas duas etapas para calcular, independentemente do tamanho do seu texto ( https://regex101.com/r/yjcs1Z/1 ).Para referência:
$^
e$.
execute 36 etapas para calcular -> O (1)\b\B
toma 1507 etapas na minha amostra e aumenta com o número de caracteres na sua string -> O (n)Tópico mais popular sobre esta questão:
fonte
Talvez isto?
fonte
re.compile('$.+^', re.MULTILINE|re.DOTALL).search('a\nb\nc\n')
retorna um objeto de correspondência correspondente aos bec (e todas as novas linhas adjacentes e intermediárias). A abordagem negativa, que recomendo, funciona (ou seja, falha em corresponder a qualquer coisa) para qualquer combinação de sinalizadores com as quais possa ser compilada.$
e^
./\z.+\A/
(veja perldoc perlre ). Isso impede que o modo de linha múltipla e linha única (use re '/ms'
) o afete.e substitua ... por todos os símbolos imprimíveis;). Isso é para um arquivo de texto.
fonte
[^\x00-\xFF]+
(para implementações baseadas em bytes).[^\s\S]
. Mas, como Ferdinand Beyer já disse, corresponderia a uma string vazia.*
; deixe isso de lado ou substitua-o por+
, e ele deve corresponder a pelo menos um caractere. Se a classe excluir todos os caracteres possíveis, não poderá corresponder a nada.E em vez de regex, basta usar uma declaração if sempre falsa? Em javascript:
fonte
Uma solução portátil que não dependerá da implementação do regexp é usar apenas uma cadeia constante que você tem certeza de que nunca aparecerá nas mensagens de log. Por exemplo, faça uma string com base no seguinte:
Claro, isso não é um desafio intelectual, mas mais como a programação de fita adesiva .
fonte
Cria um padrão que contém apenas alfanuméricos e '
-
' (nenhum dos quais são caracteres especiais de expressão regular), mas é estatisticamente impossível que a mesma sequência tenha aparecido em qualquer lugar antes (porque esse é o objetivo de um GUID).fonte