fredericopissarra Postado Julho 10, 2019 em 11:10 Compartilhar Postado Julho 10, 2019 em 11:10 Recentemente postei uma pegadinha no Discord: $ cd ~/Temp # Diretório vazio! $ echo TESTE | tr [:upper:] [:lower:] teste As sequências [:upper:] e [:lower:] não são regular expressions, mas atalhos derivados das funções em ctype.h, do C (embora essas "classes" de caracteres existam, também, no padrão estendido POSIX de regexes). Note que a tradução (tr) faz exatamente o que mandamos fazer: Converte caracteres maiúsculos (uppercase) para minúsculos (lowercase). Mas veja isso: $ touch l # cria arquivo 'l', vazio. $ echo TESTE | tr [:upper:] [:lower:] lllll Um amigo topou com isso e eu testei, achando que era algum bug na distro dele... Ué? Mas não é que o troço acontece mesmo? Por quê? O que acontece aqui é que os colchetes '[' e ']' são também usados pelo shell para especificar caracteres, num nome de arquivo. Por exemplo. Se você quiser listar todos os arquivos que comecem com a letra 'L' (maiúsculo e minúsculo), pode fazer algo assim: $ ls [Ll]* Esse '[Ll]*' é expandido pelo shell para todos os nomes de arquivos/diretórios que ele encontrar que atendam ao critério. Assim, [:lower:], sem as aspas, segue o mesmo princípio... Se existirem arquivos de 1 único caracter, cujo nome seja ':', 'l', 'o', 'w', 'e' ou 'r', o shell vai expandir o argumento para todos os arquivos que encontrar. É como se o comando, no exemplo acima, fosse: $ echo TESTE | tr [:upper:] l Se criarmos um arquivo 'r', teremos: $ touch r $ echo TESTE | tr r l r E você obtererá um erro no uso de 'tr' (porque tem um argumento extra que não deveria estar lá). Se apagar o 'l': $ rm l $ echo TESTE | tr [:upper:] [:lower:] # o mesmo que 'tr r r' TESTE O que faltou para evitar essas expansões é colocar os argumentos entre aspas: $ echo TESTE | tr '[:upper:]' '[:lower:]' # Não apaguei 'r'! :) teste Com relação à expansão pelo shell, você pode fazer um teste simples: /* test.c */ #include <stdio.h> int main( int argc, char *argv[] ) { while ( *++argv ) printf( "Arg: \"%s\"\n", *argv ); } Compilando e executando: $ cc -o test test.c $ touch l o w e r # cria os arquivos 'l', 'o', 'w', 'e' e 'r'. $ ./test [:lower:] Arg: "e" Arg: "l" Arg: "o" Arg: "r" Arg: "w" $ ./test '[:lower:]' Arg: "[:lower:]" []s Fred Link para o comentário Compartilhar em outros sites More sharing options...
Posts Recomendados
Arquivado
Este tópico foi arquivado e está fechado para novas respostas.