You are currently browsing the category archive for the 'Shell' category.
O tr é um comando muito versátil, especialmente útil para apagar caracteres indesejados.
Digamos que você peça ao usuário para digitar o número do CPF. Esse número poderá vir das mais diferentes formas, com espaços, hífens, pontos, ponto-e-vírgula e sabe mais o que que a criatividade da pessoa pode produzir.
Para preservar sua sanidade, tudo o que você quer são os números, ignorando toda a pontuação, espaços e outros caracteres. Com o tr é fácil.
$ echo 123.456.789-00 | tr -d 0-9 ..-
A opção -d apaga coisas e o 0-9 representa os números de zero a nove. Ah, note que não é necessário o uso de colchetes ao redor “[0-9]“, como muita gente costuma fazer.
Mas este comando apagou os números e deixou a pontuação, quando o desejado é o justamente o contrário. Então basta usar a opção -c, que inverte o sentido da expressão, fazendo o tr apagar tudo exceto os números:
$ echo 123.456.789-00 | tr -c -d 0-9 12345678900
Com o comando cut é fácil extrair o primeiro, segundo ou qualquer outro caractere da linha. Porém, é preciso saber a posição exata deste caractere para informá-la ao cut.
$ echo abcdef | cut -c 1 a $ echo abcdef | cut -c 2 b $ echo abcdef | cut -c 3 c
E se você quiser extrair o último caractere, independente do tamanho da linha em questão?
A primeira solução é saber qual a posição exata deste último caractere. Supondo que a linha está guardada em uma variável, use o modificador # para obter o tamanho do conteúdo da variável, ou seja, o tamanho da linha.
$ linha="abcdef"
$ echo ${#linha}
6
Agora sim, você pode usar esse truque para obter o último caractere:
$ echo $linha | cut -c ${#linha}
f
Há ainda uma outra solução, que envolve pensar diferente. Em vez de contornar a limitação do cut apelando para a expansão de variáveis do shell, que tal modificar nosso problema para que ele se enquadre nas possibilidades do cut?
- O problema: extrair o último caractere.
- O cut: sabe extrair o primeiro caractere.
- Solução: tem como fazer o último caractere ser o primeiro?
O comando rev inverte a linha, fazendo com que o último caractere seja o primeiro, e vice-versa:
$ echo abcdef | rev fedcba
Agora sim, já que nossa linha-problema foi modificada para satisfazer o cut, podemos usá-lo normalmente:
$ echo abcdef | rev | cut -c 1 f
No Linux é muito comum um daemon, durante sua execução, criar um arquivo .pid dentro de /var/run. Dentro do arquivo syslogd.pid, por exemplo, contém o PID da instância do syslogd em execução. Usa-se este mecanismo para impedir que duas instâncias do mesmo processo rodem simultaneamente e conflitem na obtenção de recursos.
Porém, a simples existência do arquivo .pid não garante que o processo esteja em execução. Ele pode ter sido fechado de uma forma inesperada e não o apagou. Então, temos que ler o conteúdo do arquivo .pid e certificar que o processo com aquele número de PID está em execução.
A forma mais fácil de fazer isso é enviando o sinal 0 para o processo. O sinal 0 é especial e não é de fato enviado, caso contrário o processo destinatário poderia ser fechado se não tratasse o sinal, mas o retorno da função indica se um sinal real seria enviado com sucesso. O código a seguir exemplifica como aplicar a técnica em C:
int main(int argc, char **argv)
{
unsigned int pid;
if (argc != 2) {
printf("Uso: %s PID\n", argv[0]);
return 1;
}
pid = (unsigned int) atoi(argv[1]);
if (!kill(pid, 0))
printf("%d esta em execucao.\n", pid);
else
printf("%d nao esta em execucao.\n", pid);
return 0;
}
A mesma técnica pode ser aplicada no terminal:
$ kill -0 123 $ echo $? # Imprime 0 se o PID 123 existir, 1 caso contrario
Note que você precisa ter permissão para enviar um sinal para um determinado processo. Para um usuário sem privilégios especiais, a dica só vai funcionar para verificar a existência de processos iniciados pelo próprio usuário.
Você tem uma lista de números, um por linha, e precisa somá-los:
$ cat numeros.txt 3 5 7 9 11 13 15
Primeiro, coloque todos em uma única linha:
$ paste -s numeros.txt 3 5 7 9 11 13 15
Agora mude o delimitador (-d) de TAB para “+”, para compor a expressão aritmética de soma:
$ paste -s -d + numeros.txt 3+5+7+9+11+13+15
Agora sim, basta passar a expressão resultante para a calculadora do shell:
$ paste -s -d + numeros.txt | bc 63
(LANG=C; ifconfig eth0|grep "inet addr"|cut -f2 -d:|cut -f1 -d" ")
Para pegar o endereço de uma interface diferente basta colocar o nome dessa interface no lugar de eth0.
É interessante que o comando seja colocado entre parênteses, para não modificar o valor da variável de ambiente LANG da sua sessão de shell atual (que controla o idioma em que os aplicativos são exibidos).
Algumas vezes uma máquina está conectada à internet de forma indireta, através de um proxy ou mesmo um firewall com múltiplos links de internet. Os comandos seguintes permitem descobrir qual IP a máquina está utilizando na internet.
Utilizando o wget:
echo $(wget -qO- http://www.whatismyip.com/automation/n09230945.asp)
Utilizando o lynx (ou o links2):
lynx -dump http://www.whatismyip.com/automation/n09230945.asp
Para calcular a raiz quadrada de um número em Shell, use o comando bc. Ele é uma calculadora completa, que entre outras funções úteis, tem a sqrt (de “square root”).
Basta mandar o comando pela entrada padrão (STDIN) e o resultado aparece na saída padrão (STDOUT):
$ echo "sqrt(16)" | bc 4 $ echo "sqrt(144)" | bc 12
Para guardar o número e o resultado em variáveis, faça assim:
numero=144 resultado=$(echo "sqrt($numero)" | bc) echo "A raiz quadrada de $numero é $resultado"
Palavras-chave: Shell, agrupar, redirecionamento
Ao fazer log da execução de um programa ou compor um arquivo de texto que agrupe a saída de vários comandos, é comum ver a seguinte estrutura ser utilizada:
comando-1 >> arquivo comando-2 >> arquivo comando-3 >> arquivo
Tudo bem, isso funciona. Mas há uma maneira mais prática e eficiente de se fazer o mesmo, que é agrupar todos os comandos e redirecioná-los para o arquivo de log uma única vez:
(comando-1 ; comando-2 ; comando-3) >> arquivo
Basta colocar todos os comandos dentro de um par de parênteses para que o shell os encare como um grupo único.
Veja um exemplo da aplicação dessa técnica e perceba uma outra vantagem: o script fica mais legível.
Log Ineficiente
echo "Iniciando em $(date)" >> /tmp/log.txt rm -vr /tmp/becape/* >> /tmp/log.txt ~/bin/meu-becape.sh --tudo >> /tmp/log.txt echo "Tamanho do becape: $(du -hs /tmp/becape)" >> /tmp/log.txt echo "Terminado em $(date)" >> /tmp/log.txt
Log Eficiente
( echo "Iniciando em $(date)" rm -vr /tmp/becape/* ~/bin/meu-becape.sh --tudo echo "Tamanho do becape: $(du -hs /tmp/becape)" echo "Terminado em $(date)" ) >> /tmp/log.txt







Comentários Recentes