Criando um box para o Vagrant

O Vagrant é um projeto que permite gerenciar ambientes virtuais de forma simples e eficiente. Ele possui suporte as principais soluções de virtualização e também para várias ferramentas de provisionamento, como Puppet e Chef·

O Vagrant empacota as máquinas virtuais em boxes que podem ser criados e depois disponibilizados no site oficial do projeto. Nesse artigo, quero mostrar como criar e disponibilizar uma box para o Vagrant. A maneira mais simples de criar um box é a partir de um box já existente, mas vou optar por criar um box do zero.

O site do Vagrant já possui boxes para as distribuições GNU/Linux mais conhecidas… Então, para criar algo diferente, vou utilizar uma distribuição menos conhecida, o Slitaz. Trata-se de uma distribuição independente( não é baseada em outra distribuição ) que na versão mais completa, com ambiente gráfico e outros programas de uso geral, cabe em uma imagem .ISO com menos de 50MB. O trabalho realizado pelos desenvolvedores do Slitaz é excelente e pode ser conferido em detalhes no site http://www.slitaz.org/en/.

Como a ideia é criar um box para o Vagrant, vou utilizar o sabor base do Slitaz que possui apenas o ambiente em modo texto e, consequentemente, uma imagem .ISO ainda menor. O download pode ser feito nesse endereço http://mirror.slitaz.org/iso/4.0/flavors/.

Para configurar o Slitaz como um box, é necessário instalá-lo em uma máquina virtual, instalar um conjunto de pacotes e configurar alguns arquivos. Para iniciar, é necessário ter o Vagrant e o VirtualBox instalados na máquina física.

Supondo que a  máquina física está usando o Debian Jessie  ou uma distribuição Debian-like, a instalação desses pacotes pode ser feita com o seguinte comando:

 
sudo apt-get install vagrant virtualbox

Feito isso, basta criar um máquina no VirtualBox e iniciar a imagem do Slitaz. O processo de boot é extremamente rápido, serão feitas algumas perguntas para localização do ambiente e o sistema já está pronto para ser utilizado. O usuário ‘root’ por padrão usa a senha ‘root’.

Por enquanto o Slitaz está rodando no modo live a partir da imagem .iso, para realizar a instalação, o primeiro passo é particionar o HD. Isso pode ser feito com o comando fdisk, assim:

Observação: Os próximos comandos devem ser executados na máquina virtual do Slitaz.

 
fdisk /dev/sda

No fdisk pressionando ‘m’ as opções disponíveis são listadas. Para criar um partição primaria, pressione ‘n’, depois ‘p’, escolha o número para partição( 1 ), escolha o inicio da partição( 1 ) e o tamanho da partição( +8000M ). Para sair do fdsik e salvar as alterações, pressione ‘w’.

Depois de criar a partição, adicione um sistema de arquivo com o comando:

 
mkfs.ext4 /dev/sda1

O próximo passo é copiar os arquivos do Slitaz para a partição do HD. A partição e o CD do Slitaz( a imagem .ISO que está no VirtualBox ) devem ser montadas com os comandos:

 
mount /dev/sda1 /mnt

mount /dev/cdrom /media/cdrom

Então, para copiar o kernel, faça:

 
mkdir /mnt/boot/

cp -a /dev/cdrom/boot/vmlinuz* /mnt/boot/

Depois, copie e descompacte o filesystem :


cp /media/cdrom/boot/rootfs.gz /mnt/

cd /mnt/

unlzma < rootfs.gz | cpio -id 

rm rootfs.gz init

Feito isso, o Slitaz já está instalado, mas antes de continuar ainda é necessário instalar o GRUB ( a primeira versão, também chamado de GRUB legacy ). Execute o comando:


grub-install --root-directory=/mnt/ /dev/sda

E crie o arquivo de configuração /mnt/boot/grub/menu.lst com o seguinte conteúdo:


timeout 5

default 0

title Slitaz
     root( hd0, 0 )
     kernel /boot/vmlinuz-2.6.37-slitaz root=/dev/sda1 vga=normal

Observação: O root( hd0, 0 ) é referente ao primeiro HD e a primeira partição, ou seja, /dev/sda e /dev/sda1. Se fosse a primeira partição do segundo HD seria root( hd1, 0 ).

O Slitaz e o GRUB estão instalados, retire a imagem do Slitaz do virtualBox e reinicie o sistema com o comando:


reboot

Boot em 4 segundos :O

Com o sistema pronto, agora é possível instalar os pacotes necessários para o Slitaz ser um box do Vagrant:


tazpkg recharge

tazpkg get-install sudo
tazpkg get-install openssh
tazpkg get-install linux-api-headers
tazpkg get-install linux-module-headers
tazpkg get-install dkms
tazpkg get-install bzip2
tazpkg get-install wget
tazpkg get-install bash

Durante a instalação do bash, o sistema vai perguntar se o sh deve ser um link para o bash, certifique-se de responder yes.

Depois, para seguir o padrão dos boxes do Vagrant, é necessário ter um usuário ‘vagrant’ com senha ‘vagrant’ e também alterar a senha do usuário ‘root’ para ‘vagrant’:


adduser vagrant

passwd

O Vagrant conecta no sistema usando SSH sem senha através de chaves, para que isso funcione, é preciso baixar a chave publica para o usuário ‘vagrant’.


mkdir /home/vagrant/.ssh/

wget --no-check-certificate https://raw.githubusercontent.com/mitchellh/vagrant/master/keys/vagrant.pub -O /home/vagrant/.ssh/authorized_keys

chown vagrant:vagrant /home/vagrant/.ssh/ -R

chmod 0700 /home/vagrant/.ssh/
chmod 0600 /home/vagrant/.ssh/authorized_keys

O usuário ‘vagrant’ também precisa poder usar o sudo sem senha, isso pode ser configurado com o comando visudo adicionando a linha:


vagrant ALL=(ALL) NOPASSWD: ALL

O próximo passo é instalar os adicionais de convidado do VirtualBox, adicione a imagem de CD na máquina virtual e execute esses comandos para realizar a instalação:


mount /dev/cdrom /media/cdrom

sh /media/cdrom/VBoxLinuxAddtions.run

Feito isso, o sistema já está quase pronto para ser um box, mas antes de terminar é importante adicionar a seguinte linha, sugerida pela equipe do Vagrant, no arquivo /etc/ssh/sshd_config:


UseDNS no

E por último, como o Vagrant utiliza apenas o comando shutdown -h now para desligar o sistema, e esse comando não está presente, de forma nativa no Slitaz( ele usa o poweroff, halt e reboot ), é necessário criar uma alternativa… Um jeito simples, é criar um shell script /sbin/shutdown com o seguinte conteúdo:


#!/bin/bash

if [ $1 = '-h' -a $2 = 'now'] ; then

     poweroff;
     exit 0;

fi

echo 'Only shutdown -h now is implemented';
exit 1;


Observação: Use o comando chmod para dar permissão de execução para o script.

Pronto, com isso, o sistema já está configurado para ser um box do Vagrant. Para terminar, desligue a máquina virtual e na máquina física execute o seguinte comando:


vagrant package --base nome_vm_slitaz

Observação: Substitua nome_vm_slitaz pelo nome da máquina do Slitaz que você criou no VirtualBox.

Com isso, foi criado o box do Slitaz com o nome ‘package.box’. Para testar, utilize os seguintes comandos:


vagrant box add slitaz package.box

vagrant init slitaz

vagrant up

Depois de testar o seu box, se quiser compartilhar, basta criar uma conta nesse link https://atlas.hashicorp.com/account/new.

Então é isso, qualquer dúvida, deixe um comentário e se quiser baixar o meu box do Slitaz, acesse: https://atlas.hashicorp.com/boxes/search?utf8=%E2%9C%93&sort=&provider=&q=p4ulodi4s

Bitwise: Multiplicando números inteiros

Nesse artigo quero mostrar como realizar a multiplicação de números inteiros utilizando apenas os operadores de bitwise da linguagem Java. Esses operadores realizam alterações diretamente nos bits e são extremamente rápidos.

A ideia para esse artigo surgiu de um exercício de lógica de programação que pedia para implementar um método de multiplicação de inteiros sem utilizar o operador da linguagem( * ). Esse é um exercício bem simples e a implementação mais comum pode ser escrita da seguinte maneira:



public static int multiplicar( int numero1, int numero2 ) {

int resultado = 0;

for( int i = 0; i < numero1; i++ )
resultado += numero2;

return resultado;
}

Esse método funciona, mas é lento… Utilizando operadores bitwise é possível implementar um método bem mais eficiente…

Apesar de oferecer maior desempenho, utilizar operadores de bitwise é mais trabalhoso e exige um pouco mais de prática. Por isso, é fortemente recomendado, antes de continuar, que seja feita a leitura desse outro artigo: http://www.prminformatica.com.br/2014/01/bitwise-escovar-bits.html.

O algoritmo que vou utilizar é similar ao método de multiplicação ensinado nas escolas. Ele é apresentado em detalhes nesse link http://www.exploringbinary.com/binary-multiplication/. Também sugiro realizar a leitura desse artigo antes de continuar…

Feita a introdução, o primeiro passo é implementar um método auxiliar que seja capaz de realizar adição dos bits. Basicamente, a adição de binários pode ser realizada com o operador xor ( em Java ^ ). Veja:

0 + 0 = 0
1 + 0 = 1
0 + 1 = 1
1 + 1 = 0 ( e vai 1) == 10

Perceba que exceto pelo último caso de teste, 1 + 1 = 10, o operador xor devolve o resultado correto. Assim sendo, para realizar a adição é possível usar o operador xor e em seguida identificar se existe o caso de teste problemático( 1 + 1 = 10 ). Se existir, é necessário utilizar novamente o xor para adicionar o 1 do ‘vai 1’. Obviamente, essa segunda operação com o xor também pode ter o caso de teste problemático… Então, é necessário refazer o teste e repetir a operação até que isso não ocorra ( uma boa oportunidade para utilizar recursividade ).

Para identificar se existe o caso de teste 1 + 1 = 10 basta utilizar o operador and ( em Java & ) com os 2 números. Veja:

0 & 0 = 0
1 & 0 = 0
0 & 1 = 0
1 & 1 = 1

Assim, se o resultado da operação and entre os 2 números for igual a zero, o caso de teste problemático não existe. Senão, o caso de teste problemático existe.

Veja uma implementação possível para o método somar:



public static int somar(int numero1, int numero2) {

if(numero2 == 0)
return numero1;

return somar( numero1 ^ numero2, (numero1 & numero2) << 1);
}

Observação: o << 1 coloca, se existir, o 1 na próxima posição a esquerda de onde ocorreu o caso de teste problemático. ( O 1 deve ser adicionado na próxima coluna da esquerda )

Com o método de adição pronto, já é possível iniciar a construção de um método para realizar a multiplicação. A multiplicação de bits pode ser realizada com o operador and, mas será necessário pegar o primeiro bit do número1 e realizar a operação and com cada um dos bits do número2 e em seguida pegar o segundo bit do número1 e realizar a operação and com cada um dos bits do número2 e assim por diante… ( Veja o link que explica o algoritmo de multiplicação )

Para pegar um bit especifico de uma variável é possível usar esse código:



int bitPosicao = ( numero & ( 0b1 << posicao ) ) >> posicao;

Nesse código, se o bit da posição escolhida for zero, bitPosicao recebe zero. Se o bit da posição escolhida for 1, bitPosicao recebe um valor diferente de zero.

Com isso, basta pegar os bits ( um do primeiro número e outro do segundo ), realizar a operação and, e armazenar o bit resultante em uma variável auxiliar de forma que ele ocupe a posição correta. Veja:



int numero1 = 0b1; //0000 0001 (apenas o primeiro byte)

int numero2 = 0b10; //0000 0010


int resultadoParcial = 0b0; //0000 0000


int posicaoBitNumero1 = 0;

int bitNumero1 = ( numero1 & ( 0b1 << posicaoBitNumero1 ) ) >> posicaoBitNumero1; // 0000 0001


int posicaoBitNumero2 = 0;

int bitNumero2 = ( numero2 & ( 0b1 << posicaoBitNumero2 ) ) >> posicaoBitNumero2; // 0000 0000

//guarda o primeiro teste na posição do bitNumero2
resultadoParcial = resultadoParcial | ( ( bitNumero1 & bitNumero2 ) << posicaoBitNumero2 ); // 0000 0000


posicaoBitNumero2 = 1; //para pegar o segundo bit do numero2

bitNumero2 = ( numero2 & ( 0b1 << posicaoBitNumero2 ) ) >> posicaoBitNumero2; // 0000 0001

//guarda o segundo teste na posição do bitNumero2
resultadoParcial = resultadoParcial | ( ( bitNumero1 & bitNumero2 ) << posicaoBitNumero2 ); // 0000 0010

Nesse exemplo, pego o primeiro bit da variável numero1 e realizo a operação and com esse bit e cada um dos bits da variável numero2. Após cada teste é usada a posição do bit da variável numero2 para armazenar o bit resultante na variável resultadoParcial. Veja que a operação or( em Java | ) entre a variável resultadoParcial e o bit resultante da operação and entre a variável numero1 e a variável numero2 não altera os bits que foram armazenados anteriormente.

Com esse exemplo, já é possível ter uma ideia dos passos necessários, mas esse processo deve ser repetido para todos os bits das variáveis numero1 e numero2. Para isso, é necessário saber qual a quantidade de bits dessas variáveis( a quantidade é igual para ambas, as duas são do tipo int ).

Em Java não existe um operador semelhante ao sizeof do C, mas a quantidade de bits de cada tipo pode ser previamente verificada. Veja esse link: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html. Utilizando esse link é possível afirmar que o tipo int têm 32 bits.

Assim sendo, é possível criar um for para pegar todos os bits da variável numero1 e um segundo for, aninhado no primeiro, para pegar todos os bits da variável numero2. Veja:



public static int multiplicarBit(int numero1, int numero2) {

int resultadoFinal = 0b0;

for (int i = 0; i < 32; i++) {

int resultadoParcial = 0b0;

int bitNumero1 = (numero1 & (0b1 << i)) >> i;

for (int j = 0; j < 32; j++) {

int bitNumero2 = (numero2 & (0b1 << j)) >> j;

resultadoParcial = resultadoParcial | ((bitNumero1 & bitNumero2) << j);
}

resultadoFinal = somar(resultadoFinal, (resultadoParcial << i));
}

return resultadoFinal;
}

Observação: Assim, estão sendo calculados zeros que não têm significância( zeros à esquerda ). É possível usar alguns métodos específicos da classe Integer para evitar isso… Fica a dica 🙂

Para testar a eficiência desse método em comparação com o método de adições consecutivas criei o seguinte código :



package javaapplication1;

public class JavaApplication1 {

public static int multiplicarSimples(int numero1, int numero2) {

int resultado = 0;

for (int i = 0; i < numero1; i++) {
resultado += numero2;
}

return resultado;
}

public static int multiplicarBit(int numero1, int numero2) {

int resultadoFinal = 0b0;

for (int i = 0; i < 32; i++) {

int resultadoParcial = 0b0;

int bitNumero1 = (numero1 & (0b1 << i)) >> i;

for (int j = 0; j < 32; j++) {

int bitNumero2 = (numero2 & (0b1 << j)) >> j;

resultadoParcial = resultadoParcial | ((bitNumero1 & bitNumero2) << j);
}

resultadoFinal = somar(resultadoFinal, (resultadoParcial << i));
}

return resultadoFinal;
}

public static int somar(int numero1, int numero2) {

if (numero2 == 0) {
return numero1;
}

return somar(numero1 ^ numero2, (numero1 & numero2) << 1);
}

public static void main(String[] args) {

int numero1 = 732222;
int numero2 = 345;

long tempoInicial = System.currentTimeMillis();

int resultado = multiplicarSimples( numero1, numero2 );

long tempoFinal = System.currentTimeMillis();

System.out.println( "Resultado simples = " + resultado + " tempo = " + (tempoFinal - tempoInicial) );

tempoInicial = System.currentTimeMillis();

resultado = multiplicarBit( numero1, numero2 );

tempoFinal = System.currentTimeMillis();

System.out.println( "Resultado bitwise = " + resultado + " tempo = " + (tempoFinal - tempoInicial) );

}

}

Observação: Eu sei que existem formas melhores de comparar a eficiência desses códigos, mas, para esse exemplo, acredito que pegar a diferença de tempo é o suficiente.

Segue os testes realizados:



//teste 0
Numero1 = 732222
Numero2 = 345
Resultado simples = 252616590 tempo = 6
Resultado bitwise = 252616590 tempo = 0

//teste 1
Numero1 = 732222
Numero2 = 9
Resultado simples = 6589998 tempo = 5
Resultado bitwise = 6589998 tempo = 0

//teste 2
Numero1 = 86
Numero2 = 3
Resultado simples = 258 tempo = 0
Resultado bitwise = 258 tempo = 0

//teste 3 - o resultado foi maior que um int
Numero1 = 123456
Numero2 = 654321
Resultado simples = -824525248 tempo = 5
Resultado bitwise = -824525248 tempo = 0

LAMP: Ubuntu 14.04, Apache, MySQL e PHP

Oi, tudo bem?

Nesse artigo quero mostrar como instalar o Apache, o MySQL e o PHP no Ubuntu. Para obter esse ambiente é comum utilizar o XAMPP ou alguma aplicação semelhante, mas quero mostrar como instalar cada um deles de forma individual usando os pacotes disponíveis nos repositórios da distribuição. Visto a popularidade das ferramentas que automatizam a instalação desse ambiente, pode parecer que a instalação de cada um desses pacotes seja uma tarefa complicada, mas no Ubuntu, e em qualquer outra distribuição GNU/Linux, esse processo é razoavelmente simples.

Antes de começar, é importante notar que as configurações mostradas nesse artigo são para um ambiente de desenvolvimento, para um ambiente de produção é necessário dar atenção a mais detalhes…

O primeiro passo é atualizar os pacotes com o seguinte comando:

 
sudo apt-get update && sudo apt-get upgrade

Com os pacotes atualizados, instale o Apache através desse comando:


sudo apt-get install apache2
 

Se o Apache foi instalado corretamente, a seguinte página vai ser visualizada na URL http://localhost:

Teste Apache

O próximo passo é instalar o MySQL. A instalação desse pacote pode ser realizada com o seguinte comando:


sudo apt-get install mysql-server
 

Durante a instalação uma tela parecida com a seguinte irá solicitar uma senha para o usuário root do MySQL.

Imagem exemplo da instalação MySQL

Depois da instalação terminar, teste o MySQL efetuando o login com o usuário root:


mysql -u root -p
 

O MySQL solicitará a senha de root que foi definida na instalação. Após informá-la, você verá uma tela como a seguinte:

Imagem exemplo prompt do MySQL

Observação: Para sair do prompt do MySQL digite o comando quit.

Se foi possível realizar o login, o MySQL está instalado corretamente. Porém, é possível acessá-lo apenas da máquina local, se quiser permitir conexões externas é necessário criar o arquivo /etc/mysql/conf.d/allow_external.cnf. com o seguinte conteúdo:


[mysqld]
     bind-address = 0.0.0.0

Agora o Apache e o MySQL já foram instalados, falta apenas o PHP. Para instalá-lo utilize o seguinte comando:

sudo apt-get install php5 php5-mysql

Para testar a instalação do PHP crie o arquivo /var/www/html/teste.php com esse conteúdo:

phpinfo();

Depois, garanta que Apache pode executar o arquivo utilizando o comando:

sudo chmod 755 /var/www/html/teste.php

Se tudo deu certo, uma página semelhante a seguinte vai ser exibida na URL http://localhost/teste.php:

Imagem exemplo PHP

O PHP já está instalado, mas sua configuração padrão está com as mensagens de erro desabilitada. Assim sendo, se houver algum erro no código de um arquivo, você não será avisado. Esse é o comportamento esperado em um ambiente de produção, mas para um ambiente de desenvolvimento é impraticável. Para permitir a exibição de mensagens de erros no PHP é necessário alterar o arquivo /etc/php5/apache2/php.ini.

Nesse arquivo procure por :

display_errors = Off

e altere para:

display_errors = On

Depois de realizar a alteração, reinicie o Apache com o comando:

sudo /etc/init.d/apache2 restart

Feito isso, o PHP vai exibir as mensagens de erro. Faça um teste, altere o arquivo /var/www/html/teste.php com o seguinte conteúdo:

erro_phpinfo();

Pronto, você instalou e configurou o seu LAMP. Porém, ainda é possível adicionar várias bibliotecas para a instalação do PHP. Para verificar uma lista das bibliotecas disponíveis use o comando:

apt-cache search php5

Será exibida uma listagem parecida com essa:

libapache2-mod-php5 - linguagem de scripts imersa em HTML, roda no servidor (módulo Apache 2)
php5 - linguagem de script incorporável em HTML, lado servidor (metapacote)
php5-cgi - server-side, HTML-embedded scripting language (CGI binary)
php5-cli - command-line interpreter for the php5 scripting language
php5-common - arquivos comuns para pacotes construídos a partir do código fonte do php5
php5-curl - CURL module for php5
php5-dbg - Debug symbols for PHP5
php5-dev - Files for PHP5 module development
php5-gd - GD module for php5
php5-gmp - GMP module for php5
php5-json - JSON module for php5
php5-ldap - LDAP module for php5
php5-mysql - MySQL module for php5
php5-odbc - ODBC module for php5
php5-pgsql - PostgreSQL module for php5
php5-pspell - pspell module for php5
php5-readline - Readline module for php5
php5-recode - recode module for php5
php5-snmp - SNMP module for php5
php5-sqlite - SQLite module for php5
php5-tidy - tidy module for php5
php5-xmlrpc - XML-RPC module for php5
php5-xsl - XSL module for php5

Para saber mais sobre um pacote utilize o comando:

apt-cache show nome_pacote

Veja um exemplo:

apt-cache show php5-pgsql

Package: php5-pgsql
Priority: optional
Section: php
Installed-Size: 219
Maintainer: Ubuntu Developers 
Original-Maintainer: Debian PHP Maintainers 
Architecture: amd64
Source: php5
Version: 5.5.9+dfsg-1ubuntu4.14
Depends: libc6 (>= 2.14), libpq5 (>= 9.0~), phpapi-20121212, php5-common (= 5.5.9+dfsg-1ubuntu4.14), ucf
Pre-Depends: dpkg (>= 1.15.7.2~)
Filename: pool/main/p/php5/php5-pgsql_5.5.9+dfsg-1ubuntu4.14_amd64.deb
Size: 51590
MD5sum: 564b17207f9e6a57bd26991fb50891f7
SHA1: 06787910a6d2a0c5718bf140bbec3a1d335c2a12
SHA256: 555463b935011fd772b3b5a717b44513e0a660c71a32caeb186d06c1c9ffce7e
Description-pt_BR: PostgreSQL module for php5
 This package provides a module for PostgreSQL database connections
 directly from PHP scripts.  It also includes the pdo_pgsql module for use
 with the PHP Data Object extension.
 .
 PHP (acrônimo recursivo para PHP: Hypertext Preprocessor) é uma linguagem
 de script de código aberto e propósito geral amplamente utilizada que foi
 especialmente implementada para desenvolvimento web e pode ser embarcada
 dentro do HTML.
Description-md5: 25edec9b992444a2c1634b9545b31326
Homepage: http://www.php.net/
Bugs: https://bugs.launchpad.net/ubuntu/+filebug
Origin: Ubuntu
Supported: 5y
...

Se quiser instalar alguns desses pacotes, use o comando:

sudo apt-get install nome_pacote1 nome_pacote2 ...

Veja o exemplo:

sudo apt-get install php5-pgsql php5-sqlite php5-ldap php5-json php5-gd

Precisa trabalhar com arquivos de texto ? AWK!

Eae pessoal, nos últimos meses eu tive que usar bastante a linguagem C para manipular arquivos de texto (txt). Apesar de ser uma linguagem poderosa, trabalhar com esses arquivos em C pode ser bem complicado. Pensando nisso, quero mostrar nesse artigo uma linguagem mais especialiazada em manipulação de arquivos de texto ( lembre-se, para quem só sabe usar martelo, tudo é prego ).

Essa linguagem é a AWK, ela foi criada em 1977 pelos cientistas Alfred Aho, Peter J. Weinberger e Brian Kernighan no laboratório Bell Labs.

Para criar os exemplos vou utilizar o arquivo “/etc/passwd”, e para que tudo ocorra de forma segura fiz uma copia desse arquivo para pasta home do meu usuário. Faça você também:



cp /etc/passwd $HOME

O meu arquivo passwd têm essa aparência:


saned:x:110:120::/home/saned:/bin/false
ntp:x:111:121::/home/ntp:/bin/false
rtkit:x:114:123:RealtimeKit,,,:/proc:/bin/false
mdm:x:108:112:Gnome Display Manager:/var/lib/mdm:/bin/false
paulo:x:1000:1000:paulo:/home/paulo:/bin/bash

Perceba que é um arquivo CSV separado por ‘:’ . Cada linha desse arquivo representa um usuário do sistema, sendo que os campos estão organizados assim:

login: senha : Id do usuario : Id do grupo : extras : pasta home : shell

Para iniciar, vou apenas usar o AWK para imprimir o arquivo no terminal, para isso digite o seguinte comando ( no terminal ) :



awk '{ print }' $HOME/passwd

O AWK fez a leitura de cada linha (uma por uma) do arquivo passwd e imprimiu na saida padrão( monitor ). Isso não é muito util, afinal, o comando cat também pode fazer isso e com uma sintaxe mais simples ( cat $HOME/passwd ). Agora vou tentar algo um pouco mais elaborado, vou imprimir o arquivo novamente, mas apenas o primeiro campo (login).



awk -F: '{ print $1 }' $HOME/passwd

Dessa vez eu utilizei o parametro -F, que especifica o separador de campos utilizado no arquivo ( nesse caso :, sem isso, o separador padrão é o TAB ou ” ” ) e passei a variável $1 ( que representa o primeiro campo ) para o print. Para cada campo da linha que esta sendo processada existe uma variável $n, onde n é a posicao do campo apartir do 1, A variavel $0 contém a linha inteira.

Para o próximo exemplo quero imprimir apenas quem utiliza o shell Bash:



awk -F: '{ if( $7 == "/bin/bash" ) print $1 }' $HOME/passwd

Obs. AWK utiliza os mesmos operadores condicionais e lógicos do C

Funcionou, mas ainda é possível melhorar a aparência dessa saída:



awk -F: ' { if( $7 == "/bin/bash" ) printf "%s usa o shell %s n", $1, $7 }' $HOME/passwd

Obs. Perceba que o printf do AWK é quase igual ao do C, ele aceita vários formatos, por exemplo: %d, %i, %f, %s e outros.

Assim fica melhor, né? No próximo exemplo quero finalizar a saída com a quantidade de campos encontrados:



awk -F: '{ if( $7 == "/bin/bash" ) { printf "%s usa o shell %s n", $1, $7; total++ } } END { printf "Total de registros %d n", total }' $HOME/passwd

Nesse exemplo utilizei o bloco END, esse bloco é executado depois que o AWK processou todo conteúdo do arquivo. Diferente do C em AWK não é necessário instanciar uma variavel. Na primeira vez que uma variável é mencionada o AWK automaticamente cria uma instância e atribui um valor inicial, para números esse valor é 0 e para strings é “”.

Caso seja necessário também é possível especificar um bloco BEGIN que é executado antes do AWK processe o conteúdo do arquivo.

O exemplo anterior ficou um pouco grande para ser executado direto no terminal, para facilitar a escrita, é possivel utilizar a AWK em forma de script, para isso basta criar um arquivo que inicie com a linha “#!/usr/bin/awk -f” e escrever os comandos nas linhas seguintes. Vai ser necessário fazer algumas adaptações, exemplo anterior em forma de script fica assim:


#!/usr/bin/awk -f

BEGIN {
FS=":";
}

{
if( $7 == "/bin/bash") {

printf "%s usa o shell %s n", $1, $7;
total++;
}
}

END {
printf "Total de registros %d n", total
}

A principal diferença é que no lugar de especificar o separador através do parametro -F, utilizo a variavel padrão FS, dentro do bloco BEGIN.

Salvei o script no arquivo teste.awk, depois dei permissão de execução para ele através do comando “chmod +x teste.awk” e para executar basta escrever no terminal “./teste.awk $HOME/passwd” . Assim fica parecido com shell script, né? ( não sabe o que é shell script? clique aqui )

Continuando, agora eu quero mostrar apenas as linhas onde o login tenha menos de 4 letras:


#!/usr/bin/awk -f

BEGIN {
FS=":";
}

{
if( length( $1 ) < 4) {

printf "%s n", $1;
total++;
}
}

END {
printf "Total de registros %d n", total
}

Nesse exemplo utilizei a função length que retorna o tamanho de uma string. Algumas das funções do AWK para trabalhar com strings são:

index( s1, s2 ) retorna a posição da string s1 na string s2
gsub( sO, sS, s ) substitui a string original sO pela a string substituta sS na sting s
length( s ) retorna o tamanho da string s
split( s, v, d ) quebra a string s usando o delimitador d e coloca no vetor v
substr( s, i, f ) retorna a parte da string s que inicia na posição i e termina na posição f

AWK também têm funções para trabalhar com números, alguma delas são:

sqrt( n ) raiz quadrada
sen( n ) seno
cos( n ) cosseno
int( n ) a parte inteira de n

No próximo exemplo vou redirecionar a saída para um arquivo e vou alterar o shell de todos os usuários que usam o “/bin/sh” para o “/bin/bash”:


#!/usr/bin/awk -f

BEGIN {
FS=":";
}

{
if( $7 == "/bin/sh") $7 = "/bin/bash";

for( i = 1; i < 8; i++ ) printf "%s:", $i >> "bkp";

print "" >> "bkp"; #pra quebrar a linha
}

Obs1. A AWK também possui uma instrução while, que assim como o for tem uma sintaxe idêntica a do C
Obs2. Os comentários em AWK são feitos com #

O exemplo anterior foi escrito ao estilo C propositalmente, eu queria mostrar como é a instrução for, o jeito AWK de fazer isso é utilizando a função gsub, assim:



#!/usr/bin/awk -f
{
gsub( "/bin/sh", "/bin/bash", $0 )

print $0 > "bkp"
}

Pessoal por hoje é isso, tem muito mais para mostrar sobre o AWK, mas fica para um próximo artigo. Para quem quiser continuar estudando o AWK, aqui fica alguns links…

http://www.inf.pucrs.br/~manssour/AWK/
http://pt.wikipedia.org/wiki/AWK
http://br-linux.org/artigos/awk_intro.htm

Bitwise. Escovar Bits

Oi, tudo bem? Depois de um tempo parado com as postagens do blog, hoje vou mostrar como trabalhar com operadores de bits em C. Essa técnica é conhecida como bitwise (e também como “escovar bits”), trata-se basicamente de usar alguns operadores para alterar a sequência de bits de uma variável.

Em C, cada variável têm um tipo, e cada um desses tipos têm um tamanho diferente( quantidade de bits ). Por exemplo, uma variável do tipo char têm o tamanho de 8 bits ( o que equivale a 1 byte ) e uma variável do tipo int geralmente têm 32 bits ( 4 bytes ).

Os principais operadores bitwise são:

  • Operador & ( and )
  • Operador | ( or )
  • Operador ^ ( xor )
  • Operador ~ ( not )
  • Operador >> ( right shift )
  • Operador << ( left shift )

Esses operadores funcionam da seguinte maneira:

& (and)

O operador & compara os bits de cada variável um por um, quando os dois bits (um da variável ‘a’ e outro da variável ‘b’) são iguais a 1 (bit ligado) o retorno é 1, caso contrário o retorno é 0.



char a = 1; // 0000 0001
char b = 5; // 0000 0101

char c = a & b; // 0000 0001

| (or)

O operador | também compara os bits de cada variável um por um, quando pelo menos um dos bits é igual a 1 o retorno é 1, caso contrário o retorno é 0.



char a = 1; // 0000 0001
char b = 5; // 0000 0101

char c = a | b; // 0000 0101

^ (xor)

O operador ^ compara os bits de forma que se os 2 bits( um da variável ‘a’ e outro da variável ‘b’ ) forem iguais ele retorna 0, caso contrario ele retorna 1.



char a = 1; // 0000 0001
char b = 5; // 0000 0101

char c = a ^ b; // 0000 0100

~ (not)

O operador ~ inverte os bits de uma variável, onde era 1 fica 0 e onde era 0 fica 1.



char a = 1; // 0000 0001

char b = ~a; // 1111 1110

<< (left shift) e >> (right shift)

Os operadores << e >> fazem o deslocamentos dos bits para direita e para a esquerda. Preenchendo o restante com 0.



char a = 1; // 0000 0001
char b = a << 2; // 0000 0100

char c = b >> 2; // 0000 0001

Nesses exemplos, utilizei os valores em base 10, mas em C, também é possível especificar valores em binario e hexadecimal. Para isso basta usar a seguinte sintaxe:



char a = 0b101; // binario
char b = 0xff; // hexa

Para tentar apresentar melhor esses operadores vou usar como exemplo um controle de quartos de um hotel. Nesse controle só é necessário saber se o quarto está livre ou se está ocupado. O hotel vai ter 8 quartos e vou armazenar as informações em uma única variável do tipo char, ou seja, cada bit vai representar um quarto. Esse não é um exemplo realista, mas com ele é possível ter uma idéia de como trabalhar com operadores de bits.

O programa inicia assim:



int main(int argc, char **argv)
{
char hotel;

hotel = 0b101; //temos 2 quartos ocupados ( 0000 0101 )

return 0;
}

O primeiro passo é desenvolver uma função para verificar se um determinado quarto está ocupado:



// o quarto é um valor entre 0 e 7 inclusive,
// seria importante testar esse valor
int estaOcupado( char hotel, int quarto )
{
char teste = 1; // 0000 0001

// rotaciona para que o bit ligado fique no quarto desejado
teste = teste << quarto;

// se o retorno for diferente de 0 o quarto esta ocupado
return hotel & teste;
}

int main(int argc, char **argv)
{
char hotel;

hotel = 0b101;

if( estaOcupado( hotel, 0 ) )
printf(" O quarto 0 esta ocupado n" );

return 0;
}

Agora vou desenvolver uma função para ocupar um quarto



void ocuparQuarto( char* hotel, int quarto )
{
char teste = 1; // 0000 0001

teste = teste << quarto;

// o bit ligado do teste garante que o quarto vai ficar ocupado,
// os outros bits do teste estão desligados e não vão alterar o hotel
*hotel = *hotel | teste;
}

int estaOcupado( char hotel, int quarto )
{
char teste = 1; // 0000 0001

teste = teste << quarto;

return hotel & teste;
}

int main(int argc, char **argv)
{
char hotel;

hotel = 0b101;

if( estaOcupado( hotel, 1 ) )
printf(" O quarto 1 esta ocupado n" );
else
printf(" O quarto 1 nao esta ocupado n" );

ocuparQuarto( &hotel, 1 );

if( estaOcupado( hotel, 1 ) )
printf(" O quarto 1 esta ocupado n" );
else
printf(" O quarto 1 nao esta ocupado n" );

return 0;
}

Por último tenho uma função para liberar um quarto:



void liberarQuarto( char* hotel, int quarto )
{
char teste = 1; // 0000 0001

teste = teste << quarto;

// inverte o teste, 0000 0001 fica 1111 1110
teste = ~teste;

// o bit desligado do teste garante que o quarto vai ser liberado,
// os bits ligados do teste não alteram o hotel.
*hotel = *hotel & teste;
}

void ocuparQuarto( char* hotel, int quarto )
{
char teste = 1; // 0000 0001

teste = teste << quarto;

*hotel = *hotel | teste;
}

int estaOcupado( char hotel, int quarto )
{
char teste = 1; // 0000 0001

teste = teste << quarto;

return hotel & teste;
}

int main(int argc, char **argv)
{
char hotel;

hotel = 0b101;

if( estaOcupado( hotel, 1 ) )
printf(" O quarto 1 esta ocupado n" );
else
printf(" O quarto 1 nao esta ocupado n" );

ocuparQuarto( &hotel, 1 );

if( estaOcupado( hotel, 1 ) )
printf(" O quarto 1 esta ocupado n" );
else
printf(" O quarto 1 nao esta ocupado n" );

liberarQuarto( &hotel, 1 );

if( estaOcupado( hotel, 1 ) )
printf(" O quarto 1 esta ocupado n" );
else
printf(" O quarto 1 nao esta ocupado n" );

return 0;
}

Bom pessoal é isso, sei que o exemplo não é muito real, mas vou deixar alguns links para quem quiser saber mais sobre a arte de escovar bits. Até a próxima postagem 🙂

http://www.diogomatheus.com.br/blog/php/operadores-bitwise-bit-a-bit/
http://samuca.wordpress.com/2007/03/26/operadores-bitwise/
http://blog.bsoares.com.br/aspnet/operacoes-binarias

Operações matemáticas com shell script

Uma coisa que chama a atenção em shell script são as operações matemáticas. Em shell script a princípio elas não são resolvidas diretamente, para resolver essas operações é necessário usar algum comando auxiliar, por exemplo:


a=1;
b=2;
# c=$a+$b; não iria funcionar
d=$(( $a + $b )); # ok

obs. também é possível usar os comandos let, expr e bc para resolver operações matemáticas.

Mas essa caracteristica apesar de ser padrão, pode ser modificada usando o comando ‘declare -i’ para criar as variáveis, veja:


a=1;
b=2;
declare –i c; # a variavel c é do tipo inteiro
c=$a+$b; # a operacao é resolvida diretamente...
# cuidado com os epaços...

Isso garante que a variável ‘c’ é do tipo inteiro, e não vai aceitar outros tipos de valores, algo parecido com o que ocorre com linguagens fortemente tipadas, mas diferentemente dessas, ao se atribuir um valor diferente do estipulado não será emitida uma mensagem de erro, veja:


declare –i c; # c é inteiro
c=”paulo”;
echo $c # imprime 0 (zero)

Ao tentar setar uma string em ‘c’ o valor é desconsiderado, ficando o valor de zero no lugar.

É importante perceber que usando o comando ‘declare -i’, além da variável assumir (parcialmente) caracteristicas de uma linguagem fortemente tipada, também terá alterações no seu escopo. Veja os exemplos:


Function teste() {
a=10;
}
teste # executa a função
echo $a #imprimie 10

Diferente de outras linguagens as variáveis dentro de funções não são por padrão locais, ou seja, elas iram escapar para o escopo principal quando a função for executada (caracteristica bem estranha, na minha opinião), mas se for usado o comando ‘declare –i’ isso não acontece:


Function teste() {
declare –i a=10;
}
teste
echo $a # nao imprimi 10

valeu pessoal, espero que seja util…

Obs. Se você precisa que as variáveis dentro de funções sejam locais e não quer usar o declare –i ou as suas variáveis não são numericas use “local a=10”;

Animações com CSS3

O CSS3 traz varias possibilidades de animações. Animações que antes envolveriam toda uma lógica de programação e algumas(ou muitas) linhas de código Javascript podem agora ser feitas apenas com CSS. Um exemplo disso é a pequena animação de aumentar uma imagem quando o mouse é colocado sobre ela. Isso já era possível apenas com o :hover, mas a idéia é que ela aumente aos poucos e não tudo de uma vez só. Na verdade, é algo bem simples, mas que até a chegada do CSS3 só era possível com Javascript. Veja um exemplo de como fazer essa animação apenas com CSS3:

#ex-css-img1 { 
width: 120px;
transition: width 2s; /* padrão */
-moz-transition: width 2s; /* Firefox */
-webkit-transition: width 2s; /* Safari and Chrome */
-o-transition: width 2s; /* Opera */
}

#ex-css-img1:hover {
width: 190px;
}

Veja a simplicidade do código, basicamente usei a propriedade “transition” para amenizar a alteração que ocorre na propriedade “width” quando o mouse fica por cima da imagem(hover). Perceba que sem a propriedade “transition” o tamanho da imagem aumenta rápidamente sem produzir a animação esperada:

Obs. no exemplo, não utilizei todas as possibilidades da propriedade “transition”, nesses casos é assumido o valo padrão.

A sintaxe da propriedade “transition” é :

transition: property duration timing-function delay;

onde:

property: A propriedade que será alterada durante a animação
duration: O tempo até que a animação termine
timing-function: A forma de execução da animação. Alguns valores suportados são: linear, ease, ease-in, ease-out…
delay: O tempo antes que a animação inicie

veja mais sobre essa propriedade aqui

Outra propriedade que simplifica e muito as animações com CSS3 é a “transform”, veja alguns exemplos:

A propriedade “transform” tem a seguinte sintaxe:

transform: function;

Onde:

“function”: É uma das muitas funções que essa propriedade suporta. Por exemplo nas animações acima usei respectivamente: transform: rotate( 180deg ), transform: rotateX( 180deg ) e transform: rotateY( 180deg ). Veja mais sobre a propriedade “transform” e suas funções aqui

Para obter resultados mais elaborados é possível especificar mais de uma propriedade para a “transition”, por exemplo:

#ex-css-img7 {
transition-property: transform, border-radius;
transition-duration: 1s;
-moz-transition-property: transform, border-radius;
-moz-transition-duration: 1s;
-webkit-transition-property: transform, border-radius;
-webkit-transition-duration: 1s;
-o-transition-property: transform, border-radius;
-o-transition-duration: 1s;
}

#ex-css-img7:hover{
transform: rotate( 360deg );
-moz-transform: rotate( 360deg );
-webkit-transform: rotate( 360deg );
-o-transform: rotate( 360deg );
border-radius: 100px;
-moz-border-radius: 100px;
-webkit-border-radius: 100px;
-o-border-radius: 100px;
}

Obs. Nesse exemplo usei a “transition” especificando cada possibilidade em uma propriedade diferente. ( da mesma forma que acontecia no CSS2, por exemplo: margim: top right bottom left; ou margin-top:, margim-right:, margin-bottom: e margin-left: )

Além das propriedades “transition” e “transform” o CSS3 também disponibiliza as propriedades “animation” e “@keyframes” (essa última na verdade é uma regra). Com elas é possível ter um maior controle sobre a animação, por exemplo:

#ex-css-img8 {
position:relative;
animation:mymove 3s infinite alternate;
-moz-animation:mymove 3s infinite alternate;
-webkit-animation:mymove 3s infinite alternate;
-o-animation:mymove 3s infinite alternate;
}

@keyframes mymove {
from {
left:0px;
}

to {
left:310px;
transform: rotate( 360deg );
border-radius: 100px;
-moz-transform: rotate( 360deg );
-moz-border-radius: 100px;
-webkit-transform: rotate( 360deg );
-webkit-border-radius: 100px;
-o-transform: rotate( 360deg );
-o-border-radius: 100px;
}
}

Essas propriedades trabalham em conjunto: A propriedade “@keyframes” define os passos da animação( from e to ou 0%,10%,20%… ), e a propriedade “animation” define a @keyframe que vai ser utilizada, o tempo até que animação se complete, a forma e quantas vezes animação será realizada. A sintaxe da propriedade @keyframes é :

@keyframes animationname { keyframes-selector { css-styles; } };;

onde:

animationname: O nome que representa a @keyframes.
keyframes-selector: Um passo na animação. Aceita valores como: from e to ou ainda em percentagem( 0%, 50%, 100%…).
veja mais sobre essa propriedade aqui

E a sintaxe da propriedade animation é :

animation: name duration timing-function delay iteration-count direction;;

onde:

name: É o nome da propriedade @keyframe que será executada.
duration: O tempo até que o efeito termine.
timing-function: Controla a forma de execução do efeito, exemplo mais lento no inicio e mais rápido no final
delay: O tempo antes que o efeito inicie.
iteration-count: A quantidade de vezes que animação será executada.
direction: A forma que animação é realizada.
veja mais sobre essa propriedade aqui

Essas são as principais propriedades para se criar animações com CSS3, os navegadores atuais já estão dando suporte à elas( ainda que com os prefixos dos navegadores ), não deixe de ver os links no final do post, neles você vai encontrar otimas animações com CSS3. Para terminar vou deixar mais um exemplo de animação com as porpriedades “animation” e “@keyframes”:

#ex-css-img9  {
position:relative;
animation: movex-css-img9 3s infinite alternate;
-moz-animation: movex-css-img9 3s infinite alternate;
-webkit-animation: movex-css-img9 3s infinite alternate;
-o-animation: movex-css-img9 3s infinite alternate;
}

@keyframes movex-css-img9 {
from {
left: 390px;
width: 120px;
}
75% {
left: 195px;
width: 60px;
transform: rotate( 360deg );
border-radius: 100px;
}
to {
left: 0px;
width: 120px;
}
}

@-moz-keyframes movex-css-img9 {
from {
left: 390px;
width: 120px;
}
75% {
left: 195px;
width: 60px;
transform: rotate( 360deg );
border-radius: 100px;
}
to {
left: 0px;
width: 120px;
}
}


@-webkit-keyframes movex-css-img9 {

from {
left: 390px;
width: 120px;
}
75% {
left: 195px;
width: 60px;
transform: rotate( 360deg );
border-radius: 100px;
}
to {
left: 0px;
width: 120px;
}
}


@-o-keyframes movex-css-img9 {

from {
left: 390px;
width: 120px;
}
75% {
left: 195px;
width: 60px;
transform: rotate( 360deg );
border-radius: 100px;
}
to {
left: 0px;
width: 120px;
}
}

mais sobre animações com css3:
http://marcobruno.com.br/example/parallax-sem-plugin-css3.html
http://www.impressivewebs.com/demo-files/css3-animated-scene/
http://devfiles.myopera.com/articles/9132/sun-rise.html
http://www.broken-links.com/2009/03/10/css-animation-pong/

Programação em Shell Script

O Shell Script é uma linguagem de programação utilizada principalmente para automatizar tarefas administrativas em sistemas operacionais Unix, Linux, BSD… Existem vários interpretadores para os scripts em shell, o mais utilizado em distribuições linux é o Bash, além dele, também é possível utilizar o Sh , Csh e o Ksh . Nesse artigo vou utilizar o Bash, veja um exemplo de Shell Script com Bash:



#!/bin/bash
echo "ola $USER";

Esse script simplesmente cumprimenta o usuário. Nele utilizei o comando “echo”, que imprime na saída padrão ( nesse caso vai ser a tela do monitor ), e a variável de ambiente “$USER”, que guarda o usuário logado. A primeira linha desse Shell Script, “#!/bin/bash”, indica o interpretador que deve executar os comandos que estão no arquivo. é possível utilizar outro interpretador shell, por exemplo o “#!/bin/sh” ou um interpretador de outra linguagem como “#!/usr/bin/python”( seria possível usar até mesmo o PHP, veja um exemplo aqui ) ou não especificar nenhum interpretador, nesse ultimo caso, o sistema usa o interpretador que estiver na variável “$SHELL” ( interpretador padrão ).

Para testar esse script é necessário que ele tenha permissão de execução no sistema, para isso, supondo que o nome do arquivo seja “teste.sh” vou rodar no terminal o comando:



chmod +x teste.sh

e depois para executar o script vou usar o comando:



./teste.sh

Para executar o Shell Script coloquei o caminho completo do arquivo teste.sh ( o “./” representa o diretório atual ), isso foi necessário porquê quando é digitado um comando ( ou um Shell ) no terminal, sem especificar o caminho até o arquivo, o sistema busca por ele nos diretórios que aparecem no variável “$PATH”. Se não quiser especificar o caminho para executar seus scripts, você pode colocá-los em um dos diretórios que aparecem na “$PATH” ou configurar o diretório onde eles estão nessa variável ( exemplo de como fazer isso aqui ).

Assim como outras linguagens de programação, Shell Script possui estruturas de controle do tipo: if, case, while e for. A Sintaxe dessas estruturas é a seguinte:

If


#!/bin/bash
nome="paulo";
if [ $nome != "paulo" ] ; then

echo "vc não é o paulo!";
fi

Case


#!/bin/bash
i=1;
case $i in

1)
echo "é 1";
;;

2)
echo "é 2";
;;

*)
echo "não eh 1 nem 2";
;;
esac

While


#!/bin/bash
i=1;
while [ $i -le 10 ] ; do

echo $i;
i=$(( $i + 1 ));
done

For


#!/bin/bash
for i in $( seq 10 ) ; do

echo $i;
done

Em Shell Script os espaçamentos que normalmente são permitidos em outras linguagens causam erros, por exemplo quando é criada uma variável não deve haver espaços entre o nome da variável, o sinal de igual e o valor atribuído.


#!/bin/bash
i=1; # ok, vai funcionar
j = 2; # não vai funcionar

Obs. é possível utilizar o comando “read” para ler da entrada padrão( geralmente o teclado ) e criar variaveis especificadas pelo usuário. Veja mais sobre isso aqui

Outra particularidade do Shell Script é que operações matemáticas não são realizadas diretamente, é necessário utilizar algum comando para realizar o calculo, por exemplo:


#!/bin/bash
i=1;
j=$(( $i + 1 )); # ok
j=$( expr $i + 2 ); # ok
j=$i + 1; # não vai funcionar como esperado

Nesse exemplo foi utilizado o comando “$( expr $i + 2 )”, basicamente trata-se de um sub-shell, o que estiver dentro de “$( )” é executado à parte e o resultado( o que seria impresso na saída padrão) é atribuído para variável. Também seria possível utilizar o comando “` expr $i + 2 `” para ter o mesmo resultado.

Outro detalhe importante que foi visto nos exemplos anteriores são os operadores usados nas estruturas de controle dentro do comando “[ ]”, que na verdade é um açúcar sintático para o comando “test”, veja alguns exemplos de operadores:

Para Numeros
-lt É menor que (LessThan)
-gt É maior que (GreaterThan)
-le É menor ou igual (LessEqual)
-ge É maior ou igual (GreaterEqual)
-eq É igual (EQual)
-ne É diferente (NotEqual)
Para Strings
= É igual
!= É diferente
Testes logicos
! Negação
-a and ( geralmente && )
-o or( geralmente || )

O Shell Script também possui funções, elas tem a seguinte sintaxe:


#!/bin/bash

function somar() {

echo $(( $1 + $2 ));
}

somar 1 2

As funções em Shell Script são chamadas da mesma forma que um comando, elas recebem parâmetros sem a necessidade de especificá-los na declaração da função. Os parâmetros são recuperados através de variáveis especais, como a “$1” e a “$2” utilizadas no exemplo acima. Veja outras dessas variáveis especiais:

$0 O nome da função
$1 O primeiro parâmetro
$2 O segundo parâmetro
$numero O parâmetro da posição numero
$# A quantidade de parâmetros
$* Todos os parâmetros

O script anterior poderia ter sido escrito da forma abaixo para não limitar o número de parâmetros a ser somados:


#!/bin/bash

function somar() {

resultado=0;
for i in $* ; do

resultado=$(( $resultado + $i ));
done

echo $resultado;
}

somar 1 2 3 4 5

Uma observação importante sobre as funções em Shell Script é que apesar de possuir a instrução “return”, essa instrução é utilizada de uma forma diferente. Em Shell Script funções são como os comandos, os comandos tem um código de retorno que indica se o comando foi executado corretamente ou não( isso é testado com a variável “$?” ), portanto as funções também tem esse código de retorno, que é retornado com a instrução “return” 🙂

Para conseguir armazenar o retorno de função em uma variável costumo usar o sub-shell:


#!/bin/bash

function somar() {

resultado=0;
for i in $* ; do

resultado=$(( $resultado + $i ));
done

echo $resultado;
}

#usando o sub-shell é possível
#armazenar o retorno da função
total=$( somar 1 2 3 4 5 );

A grande utilidade das funções é que elas organizam e garantem a reutilização de código. Uma possibilidade interessante que o Shell Script permite( e a maior parte das linguagem de script também ) e incluir um arquivo dentro de outro ( parecido com o require e include do PHP). Por exemplo, posso criar varias funções que estejam relacionadas e coloca-las no mesmo arquivo e depois quando for necessário uso a instrução “source” para incluir essas funções em outro arquivo. Supondo que a função “somar” estivesse no arquivo matemática.sh posso usá-la da seguinte maneira:


#!/bin/bash

source "matematica.sh";

total=$( somar 1 2 3 4 5 );

Além de funções e estruturas de controle, Shell Script também possui arrays. Os arrays tem a seguinte sintaxe em Shell Script:


#!/bin/bash

dias=( "domingo" "segunda" "terca" "quarta" "quinta" "sexta" "sabado" );

echo ${dias[1]}; # imprime segunda

nomes[0]="paulo";
nomes[1]="ana";
nomes[2]="carlos";

echo ${nomes[1]};

# para retornar a quantidade de itens
echo ${#nomes[@]} # imprime 3

Vou terminar deixando um script com o que foi visto nesse artigo, se quiser saber mais sobre Shell Script veja os links mais abaixo. Até mais… 🙂


#!/bin/bash
function organiza() {

array=($@);
i=0;
while [ $i -lt ${#array[@]} ]; do

j=$(($i + 1));
while [ $j -lt ${#array[@]} ]; do

if [ ${array[$j]} -lt ${array[$i]} ]; then

aux=${array[$j]};
array[$j]=${array[$i]};
array[$i]=$aux;
fi
j=$(($j + 1));
done
i=$(($i + 1));
done

for n in ${array[@]}; do

echo "$n";
done
}

organiza 2 9 4 5 6 1

Mais Informações:
http://aurelio.net/shell/canivete/pdf/canivete-shell.pdf
http://thobias.org/doc/shell_bd.html
http://thobias.org/doc/cgi_shell.html
http://www.vivaolinux.com.br/dica/Utilizando-arrays-em-shell-script
http://lendscripts.blogspot.com.br/
http://victor-dba.blogspot.com.br/2012/02/10-dicas-para-programar-em-shell-script.html

MathML: Mathematical Markup Language

MathML é uma linguagem de marcação, baseada em XML, para criar formulas matemáticas. Ela está dividida em duas partes: Presentation e Content Markup. Esse artigo vai tratar apenas da Presentation Markup.

Atualmente me parece que apenas o Firefox e o Opera oferecem algum suporte nativo para as instruções MathML( tive alguns problemas com o Opera ), mas isso provavelmente vai mudar em breve, pois a MathML está incluído na especificação do HTML5. Portanto para acompanhar esse artigo recomendo o uso de um desses navegadores ( também existe o plugin Mathplayer para IEca, mas eu não testei )

Vamos iniciar com um exemplo simples:


<math>
<msqrt>
<mn>2</mn>
</msqrt>
</math>

Essa marcação deve apresentar a raiz quadrada de 2, assim:

2

Nesse exemplo notamos que o elemento raiz do MathML é o math, a raiz quadrada é representada pelo elemento msqrt e o elemento mn representa um número.

Os elementos mais usados em MathML são mn, mi e mo. Eles servem para representar respectivamente numeros( ex. 1, 0.235 ), variáveis/constantes( ex. x, &#960 ) e operadores( ex. +, = ). Veja um exemplo usando os 3 elementos:


<math>
<mi> y </mi>
<mo> = </mo>
<mi> x </mi>
<mo> - </mo>
<mn> 3 </mn>
</math>
y = x 3

Outro elemento usado com freqüência é o mrow. Esse elemento tem a função de agrupar outros elementos em linha. A principio pode parecer um elemento sem muita utilidade, mas em MathML existem elementos com um numero especifico de filhos. Dessa forma mrow se torna muito útil. Por exemplo, o elemento mfenced serve para colocar parênteses ao redor de outro elemento, mas se for colocado mais de um elemento filho dentro dele, esses elementos são separados por vírgula, veja:


<math>
<mfenced>
<mi> x </mi>
<mo> - </mo>
<mn> 3 </mn>
</mfenced>
</math>
x 3

Essa característica pode ser útil em alguns casos, mas nesse exemplo seria melhor que não houvesse essa separação. Para evitar isso podemos fazer o seguinte:


<math>
<mfenced>
<mrow>
<mi> x </mi>
<mo> - </mo>
<mn> 3 </mn>
</mrow>
</mfenced>
</math>
x 3

Outra característica importante do elemento mfenced é que podemos especificar quais caracteres serão utilizados como parênteses e separadores. Isso é possível através dos atributos open, close e separators.


<math>
<mfenced open='[' close=']' separators='|'>

<mn> 2 </mn>
<mn> 5 </mn>
<mn> 8 </mn>

</mfenced>
</math>
2 5 8

Outro elemento que tem o numero de filhos predefinido é mfrac que serve para criar frações, o primeiro filho é o numerador e o segundo é o denominador. Segue um exemplo:


<math>
<mfrac>
<mrow>
<mn> 2 </mn>
<mo> + </mo>
<mn> 5 </mn>
</mrow>
<mn>2</mn>
</mfrac>
</math>
2 + 5 2

Ainda temos os elementos msub e msup que também tem o numero de filhos predefinidos:


<math>
<msub>
<mn> 2 </mn>
<mn> 5 </mn>
</msub>

<mo>+</mo>

<msup>
<mn> 1 </mn>
<mn> 4 </mn>
</msup>
</math>
2 5 + 1 4

Com MathML também podemos criar matrizes. A sintaxe é semelhante as tabelas html. O elemento pai é o mtable. Dentro dele temos elementos de linha mtr, e dentro desses, elementos de coluna mtd.


<math>
<mfenced><mtable>
<mtr>
<mtd> <mn> 1 </mn> </mtd>
<mtd> <mn> 0 </mn> </mtd>
</mtr>
<mtr>
<mtd> <mn> 0 </mn> </mtd>
<mtd> <mn> 1 </mn> </mtd>
</mtr>
</mfenced></mtable>
</math>
1 0 0 1

Com esse conhecimento sobre os elementos de MathML podemos criar expressões como essas:


<math>
<mrow>
<mn>x</mn>
<mo>=</mo>
<mrow>
<mfrac>
<mrow>
<mo>-</mo>
<mi>b</mi>
<mo>±</mo>
<msqrt>
<mrow>
<msup>
<mi>b</mi><mn>2</mn>
</msup>
<mo>-</mo>
<mn>4</mn>
<mo>.</mo>
<mi>a</mi>
<mo>.</mo>
<mi>c</mi>
</mrow>
</msqrt>
</mrow>
<mrow>
<mn>2</mn>
<mo>.</mo>
<mi>a</mi>
</mrow>
</mfrac>
</mrow>
</mrow>
</math>
x = b &PlusMinus; b2 4 . a . c 2 . a

<math>
<mrow>
<msub>
<mi>S</mi>
<mi>n</mi>
</msub>
<mo>=</mo>
<mfrac>
<mrow>
<mfenced>
<mrow>
<msub>
<mi>a</mi><mn>1</mn>
</msub>
<mo> + </mo>
<msub>
<mi>a</mi><mn>1</mn>
</msub>
</mrow>
</mfenced>
<mo>.</mo>
<mi>n</mi>
</mrow>
<mn>2</mn>
</mfrac>
</mrow>
</math>
S n = a1 + an . n 2

<math>
<mrow>
<msup>
<mi>a</mi><mn>2</mn>
</msup>
<mo>+</mo>
<msup>
<mi>b</mi><mn>2</mn>
</msup>
<mo>=</mo>
<msup>
<mi>c</mi><mn>2</mn>
</msup>
</mrow>
</math>
a2 + b2 = c2

Update:
13/01/2012 O Chrome gerou todos os códigos corretamente

Mais informações:
http://www.fisiocomp.ufjf.br/seminarios/MathML.pdf
http://www.w3.org/TR/MathML3/
https://developer.mozilla.org/en-US/docs/MathML/Element

POLA – Princípio da Menor Surpresa

O POLA ou Princípio da Menor Surpresa é um principio que busca evitar que o usuário seja surpreendido por um retorno não esperado. A idéia básica do POLA é a previsibilidade. Nesse post vou mostrar alguns exemplos de códigos java, que vão contra esse principio, não vou colocar o resultado, a idéia é que você tente imaginar a resposta e depois teste, ok?

Veja esse código, qual a saída dele?



Integer a = 1;
int b = 1;
Integer c = 1;

System.out.println(a == b);
System.out.println(b == c);
System.out.println(a == c);

e se for somado 999 nas três variáveis o resultado das comparações é o mesmo? O que você acha?



a += 999;
b += 999;
c += 999;

System.out.println(a == b);
System.out.println(b == c);
System.out.println(a == c);


No próximo código temos duas variáveis com a string “paulo”. O que é retornado quando comparamos as duas com o operador de igualdade(==) ? E se a comparação fosse feita com as strings em maiúsculas? O resultado é o mesmo? Têm certeza?

OBS. O certo é usar o método .equals para comparar strings



String a = "paulo";
String b = "paulo";

System.out.println(a == b);
System.out.println(a.toUpperCase() == b.toUpperCase());


Agora veja esse código, ele não compila e nem deveria, não é?



float f = 2f;

int i = 0;

i = i + f;

mas e esse, será que compila?



float f = 2f;

int i = 0;

i += f;


Por ultimo qual o resultado de 0.1 + 0.1 + 0.1 ? simples né? será?



System.out.println( 0.1 + 0.1 + 0.1 );

Mais sobre Princípios de Projetos Orientados a Objetos:
http://ferhenriquef.com
http://www.henriqueavila.com.br