sábado, 26 de abril de 2008

Manipulando logs com AWK e SED

Eis que a lista de shell script traz um bom desafio.

Galera, tenho o seguinte log.:

AAAA-------------campo_1-------------campo_2-----campo_3----campo_4----------
teste_1 371508787 371547453 38666 testetesteteste

BBBB-------------campo_1-------------campo_2-----campo_3----campo_4----------
teste_2 4625081503 4651313710 26232207 testetesteteste

Estou a tentar usar o awk com a seguinte função :
awk '$1~"teste_" {print $5";"$4}' teste > teste_.csv

a funcao busca realmente o que desejo:
$5 $4
testetesteteste 38666
testetesteteste 6232207

porem,, gostaria que seprasse da forma:

AAAA-------------
testetesteteste 38666
BBBB-------------
testetesteteste 26232207

Alguém tem uma dica de como fazer?


Ah... o bom e velho SED pode resolver isso

$ sed -rn '/(^[^-]+-+).*/{s//\1/;h};
/^teste_/{s/.* ([^ ]+) +([^ ]+$)/\2 \1/;x;p;g;p}' arquivo.log
AAAA-------------
testetesteteste 38666
BBBB-------------
testetesteteste 26232207


Ok, ok, ta muito complicado, mas veja só:

$ sed -rn '/^[^-]+-+/h;/^teste_/{x;p;g;p}' arquivo.log
AAAA-------------campo_1-------------campo_2-----campo_3----campo_4----------
teste_1 371508787 371547453 38666 testetesteteste
BBBB-------------campo_1-------------campo_2-----campo_3----campo_4----------
teste_2 4625081503 4651313710 26232207 testetesteteste


Vamos explicar
1) a opção -n serve para informar ao sed "imprima apenas quando eu mandar"
2) a opção -p serve para utilizar expressões regulares extendidas
(assim não preciso escapar o quantificador + , que significa "um ou
mais vezes", assim como os parentesis, para informar os grupos).

Eu fiz uma sacanagem. o comando h quarda o padrão num espaço chamado espaço reserva, tipo uma memória do sed, sobreescrevendo. Assim no espaço reserva eu tenho a ultima ocorrencia de uma linha do tipo, ^[^-]+-+ ,que traduzindo significa: tudo o que começa com um ou varios caracteres diferentes de -, seguidos de um ou varios - (no caso
do AAAA------------- ... ).

Agora, quando eu encontro uma linha que começa com teste_ eu:

x) troco essa linha com a linha que esta na memória (a atual
'teste_...' vai, outra volta).
p) imprimo a linha que veio (AAAA---------- ...)
g) pego a linha da memória (teste_...)
p) imprimo a linha cachorrona

Só que não fica como vc quer. Ai vc precisa fazer a sacanagem:

se uma linha NÃO tem o que eu quero, então eu a manipulo habilmente
até que ela chegue ao que eu quero


Eu poderia ter usado varias tecnicas mas... uma vez com sed, podemos continuar nele.

$ sed -rn '/(^[^-]+-+).*/{s//\1/;h};
/^teste_/{s/.* ([^ ]+) +([^ ]+$)/\2 \1/;x;p;g;p}' arquivo.log


eu transformei a primera ER em (minha_ER).* -- ou seja, criei um grupo para o que me interessa. basta fazer:

s/(minha_ER).*/\1/

para que toda a linha seja reduzida ao que a minha ER casa. em outras palavras, eu apaguei o resto da linha.

na outra eu fui mais sacana pois eu tenho 2 grupos e troco toda a linha pelos grupos, na ordem inversa. coisa de quem toma muito café e não tem escrupulos.

Vamos ver a versão AWK?

$ awk '/^[^-]+-+/{match($0,/^[^-]+-+/); x=substr($0,1,RLENGTH)}
/^teste_/{print x,"\n"$5,$4}' arquivo.log
AAAA-------------
testetesteteste 38666
BBBB-------------
testetesteteste 26232207


x, nesse caso, armazena aquele pedaço da linha anterior, que eu descobri o que é via match. match procura uma expressão regular numa string, nesse caso em $0, e seta um valor na variavel RLENGTH, que é onde a expressão acaba. basta pegar essa parte da string e guardar na variavel x, que sera lida depois.

Aqui fala um pouco dessas duas funções: http://people.cs.uu.nl/piet/docs/nawk/nawk_92.html

Eu poderia ter resolvido dessa forma também
$ awk '/^[^-]+-+/{sub(/-[^-]+.*$/,"-");x=$0}
/^teste_/{print x,"\n"$5,$4}' arquivo.log
AAAA-------------
testetesteteste 38666
BBBB-------------
testetesteteste 26232207


Entretanto aqui eu faço uma substituição grosseira do resto da linha que tem o AAAA------... por -, abusando do .* (e o fato dele ser guloso). Parece mais simples, mas está sujeito à falhas, embora não consigo pensar em nenhuma situação que seja possivem demonstrar.

AWK & SED são ferramentas sensacionais para esse tipo de problema ;-)

sexta-feira, 25 de abril de 2008

Sbado dia 26 de Abril tem FLISOL na PUC-Rio !!



Em 26 de abril, será realizado o FLISOL - Festival Latinoamericano de Instalação de Software Livre - evento de divulgação de Software Livre da América Latina. No Rio de Janeiro quem está organizando este evento é o SL-RJ. Segundo o coordenador Carlos Ferreira, “É uma ótima oportunidade para levar seus amigos para passar este dia tão importante, participando das palestras ou instalando legalmente seu computador”. O Local onde será realizado, é a PUC-Rio - Pontifícia Universidade Católica do Rio de Janeiro - Auditório do RDC, localizado na Rua Marquês de São Vicente, 225, Gávea - Rio de Janeiro, RJ - Brasil - 22453-900. Das 8:30 às 17:00.


Veja mais informações aqui:
http://installfest.info/FLISOL2008/Brasil/RioDeJaneiro

Software disponível

* Linux: Ubuntu
* Openoffice e Firefox.
* Para quem desejar, existe a opção de receber um cd da distribuição Linux Ubuntu versão 7.10, para isto basta levar um cd virgem.

Palestras

Veja aqui a grade de palestras completa.

Iremos disponibilizar uma máquina e uma pessoa para ficar durante todo o evento à disposição das pessoas interessadas em conhecer um determinado programa ou recurso, tirar dúvidas e/ou obter dicas.

Como ajudar?

Você pode ajudar o evento de diversas maneiras. A mais simples é divulgando-o para os seus amigos, na sua escola ou no seu trabalho.

Se você quiser, pode ser um instalador ou palestrante no InstallFest. Envie um e-mail para Carlos Ferreira ou Luiz Aldabalde falando um pouco sobre a sua experiência com GNU/Linux ou qualquer outra aplicação livre que seja instalada durante o evento.

Caso queira ajudar de qualquer outra forma, entre em contato conosco por e-mail. Toda a ajuda é bem vinda!

O que devo fazer para me preparar para o Install Fest?

ATENÇÂO: Maquinas do tipo Desktop(com gabinete) só poderão entrar no Campus da PUC-Rio até as 12:00 horas, após este horário somente laptops dentro de mochilas.

Checagem de Hardware: No Windows, vá até o Painel de Controle e escolha Sistema. Liste:

* Placa de rede (marca, modelo, configuração)
* Placa de vídeo (marca, modelo, configuração)
* Placa de Som (marca, modelo, configuração)
* CPU (Processador)
* Memória RAM
* Modem (marca, modelo, configuração)
* Espaço livre em disco (mínimo de 5.0 Gb)
* Componentes SCSI (se houver algum)

* Faça backup dos seus dados. Por precaução, você deve fazer uma cópia dos seus dados importantes no computador do seu amigo ou em CD-ROM.

* Particionamento do disco: se você souber como fazer, faça uma partição de no mínimo 5.0 Gb. Quanto maior for essa partição, mais utilidades do Linux poderão ser instaladas. Se você não souber fazer isso, nós faremos no dia do Install Fest. Apenas irá demorar mais tempo.

* Desfragmento do disco: Se você não souber fazer o particionamento, desfragmente o seu disco. Se você não souber fazer isso, ou não quiser, nós o faremos no dia do Install Fest. Apenas a sua instalação demorará mais que se você o tivesse feito antecipadamente. Para desfragmentar no Windows, primeiro desabilite todos os programas. Isso incluirá ICQ, navegadores, anti-vírus ou qualquer outra coisa que você estiver rodando. A seguir, clique em Iniciar, Programas, Acessórios, Desfragmentador de Disco. A seguir, clique em Iniciar na janela que aparecer nesse instante.

* Os custos de transporte do seu PC são de sua responsabilidade.

* Trazer para o Install Fest o Gabinete,Teclado, mouse e ainda, cabos de comunicação CPU-Periférico e cabos de força. Enfim, tudo o que é necessário para fazer seu computador funcionar. Se possível, traga também os manuais do seu hardware.

Apoio

CASA DO MOODLE http://www.casadomoodle.com

Responsáveis

Coordenador:
o Carlos Henrique Lucas Ferreira

Colaboradores:
o Luiz Guilherme Aldabalde
o Avalci Suzano
o Carlos Eduardo(Cadunico)
o Luis Felipe Costa
o Bruno Garcia
o Josir Gomes

domingo, 20 de abril de 2008

Sobre o FISL e tudo mais

Rapidamente, foi ótimo reencontrar os amigos de Porto Alegre. Os ultimos dias do FISL me cansaram demais, porém foi ótimo conversar pessoalmente com o Aurélio (alias o livro dele é ANIMAL! vale a pena adquirir!), rever o Julio Neves, a galera do Tchelinux, sem falar na galera que eu conheci no evento (que eu insistia em trocar o nome, procedência, etc). Um abraço especial pro Marcelo Martins, que deve estar em Torres agora.

Destaque para a palestra do Guilherme Chapiewski.

Devo me preparar melhor para os próximos eventos, tanto em Poa ano que vem quanto os próximos eventos (como o FLISOL dia 26 de Abril na PUC-RJ, sem falar no Hack'n Rio). To doido pra ir no Javauy 2008 mas acho que não vai rolar :( Estou cheio de ideias!

Peço desculpas a todos que não conseguiram me encontrar ou que não pude conversar direito! Forte Abraço!

domingo, 13 de abril de 2008

Um corretor ortográfico em gawk

Ano passado eu publiquei uma pequena nota sobre um pequeno corretor ortográfico feito em Python.

No artigo do Peter Norwig, ele explica o principio estatístico do algoritmo. No final, ele mostra varias implementações do algoritmo (em D, Java, Ruby e até Erlang).

Depois de muito pesquisar, decidi fazer uma versão em gawk. A primeira tinha 30 linhas e não funcionava muito bem, arrumando e testando cheguei a esta forma final com apenas 15 linhas.

Eu chamo de linha um statement completo do awk. Perceba que nenhuma linha dessas possui o separador de statement ; (ponto-e-virgula), exceto quando estou utilizando o for no estilo C.

# Usage: gawk -v word=something -f thisfile.awk [ big.txt [ big2.txt ... ]]
# Gawk version with 15 lines -- 04/13/2008
# Author: tiago (dot) peczenyj (at) gmail (dot) com
# Based on : http://norvig.com/spell-correct.html
function edits(w,max,candidates,list, i,j){
for(i=0;i< max ;++i) ++list[substr(w,0,i) substr(w,i+2)]
for(i=0;i< max-1;++i) ++list[substr(w,0,i) substr(w,i+2,1) substr(w,i+1,1) substr(w,i+3)]
for(i=0;i< max ;++i) for(j in alpha) ++list[substr(w,0,i) alpha[j] substr(w,i+2)]
for(i=0;i<= max ;++i) for(j in alpha) ++list[substr(w,0,i) alpha[j] substr(w,i+1)]
for(i in list) if(i in NWORDS) candidates[i] = NWORDS[i] }

function correct(word ,candidates,i,list,max,temp){
edits(word,length(word),candidates,list)
if (!asort(candidates,temp)) for(i in list) edits(i,length(i),candidates)
return (max = asorti(candidates)) ? candidates[max] : word }

BEGIN{ if (ARGC == 1) ARGV[ARGC++] = "big.txt" # http://norvig.com/big.txt
while(++i<=length(x="abcdefghijklmnopqrstuvwxyz")) alpha[i]=substr(x,i,1)
IGNORECASE=RS="[^"x"]+" }

{ ++NWORDS[tolower($1)] }

END{ print (word in NWORDS) ? word : "correct("word")=> " correct(tolower(word)) }


Veja o script em funcionamento:
$ time gawk -v word=somethink -f spelling.awk
correct(somethink)=> something

real 0m4.862s
user 0m4.702s
sys 0m0.093s

sábado, 5 de abril de 2008

Participe do Domingão do Faustão

Vou fazer uma propaganda descarada: o Domingão do Faustão lançou o quadro Dança da Galera!

Para participar, basta seguir as instruções aqui e enviar o seu vídeo!

2008 promete muitas novidades! Aguardem!

sexta-feira, 4 de abril de 2008

Venha Tomar um Chimarrão no Estande da Globo.com!

Acompanhando o post do Guilherme, dia 18 eu devo aparecer por Porto Alegre, para o FISL.

Venha Tomar um Chimarrão no Estande da Globo.com durante o FISL!

quarta-feira, 2 de abril de 2008

Programando em C para console - parte 1

(Depois de um fecundo primeiro de Abril... )

Cada vez mais eu me espanto com a quantidade de novatos que tentam fazer programas para o "modo console" que não fazem o menor sentido.

Programas com menuzinho (1 - saque , 2 - deposito, 3 - sair) ou do estilo "digite um numero (q para sair)" são totalmente contra-produtivos. O novato perde TEMPO fazendo um monte de código desnecessário quando esquece o que deveria fazer (o tal do algoritmo).

Veja um exemplo: um programa que receba uma quantidade variavel de números e que imprima a soma dos mesmos. IMHO a forma mais interessante para fazer isso é pegar os números como argumentos do programa principal. Vc cria um programa console absolutamente limpo e facil de scriptar, por exemplo.

Veja só:

#include <stdio.h>

int main(int argc, char *argv[]){
double soma = 0.0;

printf("A soma dos numeros eh %g\n",soma);

return 0;
}


Feito esse simples arquivo, vamos compilar
$ gcc -Wall soma.c
$ ./a.out 1 2 3 4 5
A soma dos numeros eh 0


Ai vc fala "po, ta errado!", mas claro, eu primeiro escrevi a base do meu programa. Perceba que eu compilei com a opção -Wall, que me informa todos os warnings que a compilação pode gerar (o que sempre é uma excelente pratica, eu procuro compilar sempre com 0 warnings).

Feito isso, vamos definir 2 coisas:
- O algoritmo da soma e
- Possiveis fluxos de excessão.

Vou partir do suposto que, se vc digitar alguma coisa que não seja um numero, eu vou ignorar e considerar como 0. Caso eu não informe nenhum numero ao programa, isso significa que estou faltando com alguma coisa, nesse caso vou informar uma mensagem elucidativa sobre o uso do programa.

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]){
int i;
double soma = 0.0;

if(argc == 1){
fprintf(stderr,"Faltando Argumentos!\n");
fprintf(stderr,"Uso: %s x1 [ x2 .. xN ]\n",argv[0]);
return 1;
}

for(i=1;i<argc;i++)
soma += atof(argv[i]);

printf("A soma dos numeros eh %g\n",soma);

return 0;
}


Todos os argumentos que eu passo para o programa, incluindo o nome do mesmo, ficam no vetor argv, e o número de argumentos fica na variavel arcc. Dessa forma, o nome do programa é o argv[0] e, se eu não passar nenhum argumento adicional, argc será 1. A função atof converte a string para um número de ponto flutuante e retorna 0 se não for possivel converter.

Simples, não? Agora vamos executar:

$ ./a.out          
Faltando Argumentos!
Uso: ./a.out x1 [ x2 .. xN ]
$ echo $?
1
$ ./a.out 1 2 3 4 5
A soma dos numeros eh 15
$ echo $?
0


A mensagem de uso utiliza uma notação no manual de alguns programas do mundo unix: colocar os argumentos opcionais entre colchetes. Eu informo que preciso de pelo menos um argumento. Caso eu entre no fluxo de excessão, o meu main retorna um valor diferente de 0 para o sistema operacional que pode ser capturado pela variavel de ambiente $? (nesse caso estou em um linux utilizando o bash, em outros sistemas mais exotéricos como o Windows eu não imagino como vc poderia capturar essa informação, tampouco imagino se ela seria util).

Perceba que eu posso criar um script extremamente simples para utilizar esse programa, assim como testar o resultado é uma tarefa de um grep (ou diff). Eu poderia juntar um script de teste e um makefile nesse post mas estou esperando um exemplo um pouco mais interessante.

Eu criei um programa sucinto, facil de entender e muito util, sem ter que perguntar para o usuario nada. transformar esse programa num que calcula a média, por exemplo, é uma tarefa de colocar apenas uma linha (na verdade uma subtração e uma divisão) a mais. Espero que os programadores novatos se inspirem nessa forma de pensar e que utilizem os programas básicos do unix como o grep, cat, diff, cp, etc, para seus futuros trabalhos.

terça-feira, 1 de abril de 2008

Java 1.7 vai ter Ponteiros!!!

Sensacional.

Um dos recursos mais uteis do C finalmente conquistou o mundo java: a notação de ponteiros do Kernighan & Ritchie.

public class Example{
public static void main(String [] args){
int *x, y=0;
x = &y;
System.out.println("O valor de x eh " + *x);
}
}


Agora será possivel fazer, em java:

- Passar primitivos por referência.
- Usar malloc, realloc e free.
- Utilizar ponteiros void para converter uma URL em String, ou um Throwable em um List.
- Sem falar que as Strings terão um caracter a mais no fim: o famoso \0 (na verdade a classe String deve desaparecer no Java 1.8, sendo substituida pelo bom e velho array de char)

Parabéns Sun!

WhiteSpace Server Pages

E... para completar o dia:

<?WhiteSpace
Say hello.













































































































?>

Novas Tecnologias .Net

A Microsoft resolveu contra-atacar a proposta da SUN com o FSP que, de uma tacada só, 6 novas linguagens no mundo dot NET: vejam exemplos dos novissimos ABAP .Net, ASM .Net, BrainFuck .Net, JCL .Net e VHDL .Net.

Para a parte web, vc poderá utilizar qualquer uma destas linguagens. Todas serão compiladas para CLI pelo ISS. A nova tecnologia permite, inclusive, rodar um .BAT, veja os exemplos abaixo!

<?ABAP
REPORT ZHB00001.
WRITE: 'Hello world'.
?>


<?ASM
SECTION .data

msg db "Hello, world!",0xa ;
len equ $ - msg

SECTION .text
global main

main:
mov eax,4
mov ebx,1
mov ecx,msg
mov edx,len
int 0x80

mov eax,1
mov ebx,0
int 0x80
?>


<?BRAINFUCK
++++++++++[>+++++++>++++++++++>+++<<<-]>++.>+.+++++++
..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.
?>


<?MSDOS
@ECHO OFF
REM Hello World for DOS batch

ECHO Hello World!
?>


<?JCL
//HERIB JOB ,'HERIBERT OTTEN',PRTY=12
//* Hello World for MVS
//HALLO EXEC PGM=IEBGENER
//SYSPRINT DD SYSOUT=*
//SYSUT2 DD SYSOUT=T
//SYSUT1 DD *
Hello World!
/*
//
?>


<?VHDL
ENTITY helloworld IS
END helloworld;

ARCHITECTURE hw OF helloworld IS

BEGIN

ASSERT FALSE
REPORT "HELLO, WORLD!"
SEVERITY NOTE;

END hw;
?>


Essa microsoft...

FSP - Fortran Server Pages!

Sensacional.

A SUN está ressucitando uma das mais velozes linguagens de todos os tempos. Uma nova tecnologia web foi anunciada hoje: Fortran Server Pages!


<?FORTRAN
*
C Hello World in Fortran 77
C (lines must be 6 characters indented)
*
PROGRAM HELLOW
WRITE(UNIT=*, FMT=*) 'Hello World'
END
?>


A ideia é atingir um novo patamar em sistemas web.

Fonte: Google