Diferença entre \ A \ z e ^ $ nas expressões regulares do Ruby

196

Na documentação que li:

Use \ A e \ z para corresponder ao início e fim da sequência, ^ e $ correspondem ao início / fim de uma linha.

Vou aplicar uma expressão regular para verificar o nome de usuário (ou o e-mail é o mesmo) enviado pelo usuário. Com qual expressão devo usar validates_format_ofno modelo? Não consigo entender a diferença: sempre usei ^ e $ ...

collimarco
fonte

Respostas:

226

Se você estiver dependendo da expressão regular para validação, sempre desejará usar \Ae \z. ^e $corresponderá apenas até um caractere de nova linha, o que significa que eles poderiam usar um email como [email protected]\n<script>dangerous_stuff();</script>e ainda assim validá-lo, pois a regex vê apenas tudo antes do \n.

Minha recomendação seria remover completamente novas linhas de um nome de usuário ou e-mail com antecedência, já que não há praticamente nenhuma razão legítima para isso. Então você pode usar com segurança QUALQUER \A \zou ^ $.

Lucas
fonte
13
@Ragmaanir está certo, deve ser com letra minúscula em \zvez de \Z!
Petr
10
+1 Obrigado! Embora eu deva discordar de sua recomendação: A) Não adicione trabalho / processamento desnecessário se houver um catch-all apropriado; e B), especialmente se não permitir que você tenha preguiça de distinguir os dois. Você pode nem sempre estar em posição de manipular as strings, apenas para o Regex, portanto, comprometa o correto na memória e saiba a diferença!
Dooleyo 25/03
1
Eu não entendi o exemplo com coisas perigosas porque, em ambos os casos, é possível incluir coisas perigosas na string, com ou sem novas linhas, seria uma exploração que deveria ser corrigida com sanitização e validação de html.
Jayr Motta
2
@JayrMotta, o que a demonstração mostra é que as coisas perigosas ignorariam completamente toda a sua verificação de regex . Portanto, mesmo se você estivesse procurando coisas perigosas no seu regex, isso seria ignorado se você $verificasse "fim da string" em vez de \z.
Doctor Blue
177

De acordo com Pickaxe :

^ Corresponde ao início de uma linha.

$ Corresponde ao final de uma linha.

\A Corresponde ao início da string.

\z Corresponde ao final da sequência.

\Z Corresponde ao final da sequência, a menos que a sequência termine com a "\n", caso em que corresponde imediatamente antes de "\n".

Então, use \Ae em minúsculas \z. Se você usar \Zalguém, pode se infiltrar em um caractere de nova linha. Acho que isso não é perigoso, mas pode estragar algoritmos que assumem que não há espaço em branco na string. Dependendo da sua expressão regular e das restrições de comprimento, alguém pode usar um nome invisível com apenas um caractere de nova linha.

A implementação do Regex por JavaScript trata \Acomo um literal 'A'( ref ). Portanto, observe-se lá fora e teste.

Ragmaanir
fonte
16

O início e o fim de uma sequência podem não ser necessariamente a mesma coisa que o início e o final de uma linha. Imagine se você usou o seguinte como sua sequência de teste:

meu
nome
é
andrew

Observe que a corda tem muitas linhas nele - o ^e $caracteres permitem que você combinar com o começo eo fim dessas linhas (basicamente tratam o \npersonagem como um delimitador), enquanto \Ae \Zpermitem que você para combinar com o início eo fim de toda a cadeia.

Andrew Hare
fonte
1
Melhor resposta na minha opinião. "basicamente tratando o caractere \ n como um delímetro" realmente me ajudou a entender, obrigado.
Flyout91
11

Diferença por exemplo

  1. /^foo$/corresponde a um dos seguintes, /\Afoo\z/não:
whatever1
foo
whatever2
foo
whatever2
whatever1
foo
  1. /^foo$/e /\Afoo\z/todos correspondem ao seguinte:
foo
Chun Yang
fonte