[Rio-pm] Isso não deveria estar certo???

Aureliano Guedes guedes_1000 em hotmail.com
Sábado Dezembro 8 18:12:39 PST 2012


Breno, so uma duvida, antigamente eu usava muito arquivos temporario, eu deixei de usar pois achava que perdia muito em performance.

Você acha que eu perco muito em performance usando a solução 4 no lugar das outras soluções?

From: guedes_1000 em hotmail.com
To: rio-pm em pm.org
Date: Sat, 8 Dec 2012 10:13:53 +0000
Subject: Re: [Rio-pm] Isso não deveria estar certo???





Breno++, eu precisei mover esse e-mail para pasta "importantes" assim como fiz com aquele ultimo que me ajudou. 
Dicas assim não se pode deixar perder.

Lerei sim os links que me passou. E sim, a duvida foi respondida. E não recebei como bronca, nem fiquei chateado ou algo do tipo.

Não sei o que dizer alem de: "Obrigado".

> Date: Sat, 8 Dec 2012 03:40:15 -0200
> From: breno em rio.pm.org
> To: rio-pm em pm.org
> Subject: Re: [Rio-pm]	Isso não deveria estar certo???
> 
> Oi Aureliano,
> 
> cara, antes de tudo, parabéns. O exemplo que vc colou no email mostra
> que vc está prestando atenção no que é dito aqui na lista. Seus
> códigos estão agora com strict (faltou só o 'warnings', hein?), usando
> autodie, open com 3 argumentos, muito bom mesmo! Agora, pra ficar
> perfeito, falta só uma coisa: por favor, antes de mandar dúvidas,
> lembre que as pessoas daqui da lista não estão sentadas aí do seu lado
> olhando o seu problema, nem vivendo o seu dia-a-dia para saber os
> motivos e objetivos do código, tampouco possuem (eu pelo menos não
> possuo) poder de ler mente :-)
> 
> Por exemplo, quando vc pergunta algo do tipo:
> 
> > Monges, cade o erro???
> 
> Fica faltando o clássico grupo: "o que vc está tentando fazer, de modo
> geral? No código específico, o que deveria estar acontecendo mas não
> está? Ainda no código específico, o que está de fato acontecendo em
> vez do que deveria?"
> 
> Quando, mesmo depois do Junior Moraes matar a charada, vc continua com:
> 
> > Mas me diz uma coisa, como editar um arquivo.
> 
> A gente tem que se esforçar até pra saber que é uma pergunta, mais
> ainda qual é a real pergunta por trás da pergunta. "Como editar um
> arquivo" é quase tão vago quanto "Preciso saber o que estou errando
> aqui" (retirado de outra thread que vc começou). Percebe o padrão?
> 
> Isso não é uma bronca. Mas, pensa comigo: se der a impressão que vc
> não está se esforçando nem pra fazer a pergunta, pq alguém se
> esforçaria pra te dar a resposta? A atividade na lista é voluntária e
> não remunerada, feita por pessoas com um interesse em comum (Perl) e
> que se dispõem a ajudar umas às outras em seu tempo livre. Por isso
> mesmo, se vc quer respostas melhores e mais rápidas, precisa nos
> ajudar a te ajudar! Por exemplo, experimente ler suas perguntas em voz
> alta antes de enviar o email, e veja se elas deixam realmente claro o
> que você está perguntando. Existe um texto muito bom sobre isso
> chamado "Como fazer perguntas inteligentes" mas também é grande e tem
> muitas coisas lugar-comum que você certamente já sabe. Se me permite a
> sugestão, vá direto nessas aqui, que são onde (eu pelo menos) sinto
> mais dificuldade:
> 
> http://www.istf.com.br/perguntas/#writewell
> http://www.istf.com.br/perguntas/#beprecise
> http://www.istf.com.br/perguntas/#symptoms
> http://www.istf.com.br/perguntas/#goal
> http://www.istf.com.br/perguntas/#examples
> 
> Não estou falando isso pra vc ficar chateado, pelo contrário! Estou só
> tentando te ajudar a nos ajudar, e assim tirar maior proveito das
> listas e melhorar cada vez mais. Os parágrafos acima são uma leitura
> super rápida, pense como um investimento: vc vai gastar menos de 5
> minutos pra ler (e está traduzido em português!) e se prestar atenção
> nesses pontos, tenho certeza que daqui pra frente você vai conseguir
> respostas muito mais rapidamente nessa e em qualquer outra lista!
> 
> Dito isso, deixa eu tentar te ajudar. Eu *acho*, depois de perder um
> bom tempo olhando pro seu exemplo, que a sua pergunta é:
> 
> "Pessoal, como eu faço pra abrir o mesmo arquivo tanto para leitura
> quanto para escrita?"
> 
> ou
> 
> "Pessoal, como eu faço para ler e escrever no mesmo arquivo, ao mesmo tempo?"
> 
> 
> Se for isso mesmo, é uma pergunta super comum. E, como a maioria das
> coisas em Perl, há mais de uma maneira de se fazer :)
> 
> Digamos, para efeito de exemplo, que você queira passar o nome de um
> arquivo como parâmetro para o seu programa. O arquivo tem o formato:
> 
> ----------8<-----------
> >blablabla
> ACTGAACAGTAGCTACTGACTCGTACGCTCGTAGC
> >lalalala
> CAGCTGATCGATCGTAGCATGCTACG
> ---------->8-----------
> 
> E o que você quer é transformar esse arquivo em algo como:
> 
> ----------8<-----------
> >contig0
> ACTGAACAGTAGCTACTGACTCGTACGCTCGTAGC
> >contig1
> CAGCTGATCGATCGTAGCATGCTACG
> ---------->8-----------
> 
> Claro, não só duas linhas e sim centenas, mas acho que deu pra entender.
> 
> 
> Solução 1 (one-liner)
> ================
> 
> perl -i -pe 'BEGIN { $i = 0 } $i++ if s{^>.+$}{>contig$i}' arquivo.txt
> 
> Essa solução usa perl como ferramenta para transformação de arquivos
> "in place". O "-pe" executa o código entre aspas para cada linha do
> arquivo passado, imprimindo o que estiver em $_ no final do
> processamento de cada linha. O código em si é simples: substitua
> "^>.+$" (início de linha seguido de ">" seguido de qualquer coisa,
> seguido do fim da linha) pela string ">contig$i", onde $i é um número
> que começa com zero (por isso o BEGIN { $i = 0 }, senão $i começa
> vazio, e a primeira linha vira apenas ">contig" em vez de ">contig0").
> Sempre que conseguir fazer essa substituição (ou seja, sempre que a
> linha em questão casar com a regex do lado esquerdo do s{}{}),
> incremente o valor de $i. Assim, quando a linha casar com a regex, a
> substituição sera feita, o $i será incrementado, e a linha será
> impressa (por causa do "-p"). Se a linha não casar com a regex, nada
> será feito e a linha será impressa sem mudanças (de novo, por causa do
> "-p").
> 
> Executando apenas com o "-pe", ele vai imprimir na tela o resultado
> pra vc. Isso significa que vc pode redirecionar pra outros arquivos,
> se quiser. Mas como em nosso problema queremos que o próprio arquivo
> seja modificado, usamos a opção "-i" (de "in place"), que escreve a
> saída no próprio arquivo de entrada pra você, sem que você precise
> ficar se preocupando com criação e cópia de arquivos temporários. Se
> quiser manter o original para fins de backup, basta trocar "-i" por
> "-i.bak", e o perl manterá uma cópia do original em "arquivo.txt.bak".
> 
> Mais detalhes: perldoc perlrun
> 
> 
> 
> Solução 2 (one-liner, em arquivo)
> ==========================
> 
> ----------8<-----------
> #!/usr/bin/env perl -pi
> BEGIN { $i = 0 }
> $i++ if s{^>.+$}{>contig$i}
> ---------->8-----------
> 
> One-liners são bacanas, mas são também difíceis de manter e de
> lembrar. Uma alternativa é copiá-los para arquivos que podem ser
> executados normalmente. Sabe o "shebang", aquela linha com "#!" que
> chama o "perl"? Você pode passar parâmetros por ela também. No caso,
> estamos passando "-p" e "-i" juntos ("-pi"), já que não precisamos do
> "-e" pois o código está no próprio arquivo. Repare também que o "-i"
> tem que ser o último parâmetro (sem nada depois), pois se
> escrevessemos "-ip" o perl vai achar que vc quer editar o arquivo e
> gravar um backup com extensão "p".
> 
> Claro que um "one-liner em arquivo" é difícil de manter, porque vc tem
> que prestar atenção nos modificadores passados (em nosso caso, "-pi")
> e fazer a "tradução" de cabeça do que de fato está acontecendo. Também
> tem que, idealmente, adicionar strict, warnings, declarar variáveis,
> aquilo tudo que é imprescindível para um programa profissional e fácil
> de manter. Para contornar esse problema, você pode procurar soluções
> como o App::Rad para converter seus one-liners em programas, ou
> simplesmente continuar lendo :)
> 
> 
> 
> Solução 3 (alteração in-place, versão extendida)
> =====================================
> 
> ----------8<-----------
> #!/usr/bin/env perl
> use strict;
> use warnings;
> 
> # para mudar arquivos 'in-place'
> # vindos do ARGV.
> local $^I = q{};
> 
> my $i = 0;
> while ( my $linha = <ARGV> ) {
>   if ($linha =~ s/^>.+$/>contig$i/ ) {
>     $i++;
>   }
> }
> continue {
>   die "erro editando arquivo in-place: $!\n"
>     unless print $linha;
> }
> ---------->8-----------
> 
> Essa versão é a forma "extendida" do one-liner. Acho legal ver como
> uma simples linha se transforma dessa forma, dá outra perspectiva para
> quanto o perl facilita a nossa vida (outra comparação que sempre me
> impressiona é Moose x OO tradicional, mas isso é outro papo). A
> primeira coisa a notar é que estamos inicializando a variável local
> $^I, uma variável especial do Perl que transforma os arquivos de
> entrada nos próprios arquivos de saída, exatamente como o "-i" faz na
> linha de comando. Colocamos a string vazia pois, nesse exemplo, não
> estamos gravando backup do original. Depois, lemos o conteúdo dos
> arquivos linha-a-linha e fazemos nossa já conhecida substituição e
> incremento do $i (dessa vez botei o if na forma "ativa", pra mostrar
> que tanto faz: vale o que ficar mais claro para você). Finalmente,
> termos o bloco "continue", que é executado no final de cada linha.
> Poderíamos ter escrito nosso while sem o continue, assim:
> 
> ----------8<-----------
> while ( my $linha = <ARGV> ) {
>   if ($linha =~ s/^>.+$/>contig$i/ ) {
>     $i++;
>   }
>   die "erro editando arquivo in-place: $!\n"
>     unless print $linha;
> }
> ---------->8-----------
> 
> Mas, se o efeito é o mesmo, pq usar continue? Simples: se amanhã vc
> quiser incrementar seu parser e pular linhas, sair do loop, etc, o que
> estiver dentro do bloco continue será executado mesmo após chamar
> "next". O efeito é o mesmo, e vc pode deixar sem o "continue" se te
> confundir (apenas lembre que ele existe, caso precise desse recurso no
> futuro).
> 
> Para mais informações: perldoc -f continue
> 
> 
> 
> Solução 4 (usando arquivos temporários)
> ================================
> 
> ----------8<-----------
> #!/usr/bin/env perl
> use strict;
> use warnings;
> use autodie;
> 
> my $nome_original = 'arquivo.txt';
> my $nome_tmp      = 'tmp.txt';
> 
> open my $orig_fh, '<', $nome_original;
> open my $tmp_fh,  '>', $nome_tmp;
> 
> my $i = 0;
> while ( my $linha = <$orig_fh> ) {
>   if ($linha =~ s/^>.+$/>contig$i/ ) {
>     $i++;
>   }
> }
> continue {
>     print $tmp_fh $linha;
> }
> 
> close $orig_fh;
> close $tmp_fh;
> rename $nome_tmp => $nome_original;
> ---------->8-----------
> 
> Essa abordagem com arquivo temporário usa menos memória do que a
> solução sem arquivos temporários mais abaixo. Também é mais segura de
> trabalhar e fácil de entender, e te dá a oportunidade de gravar um
> arquivo de backup - é só adicionar um rename($nome_original =>
> "outro_nome") antes do rename que está na última linha do exemplo.
> Outra vantagem é que vc pode gravar o nome dos arquivos de origem
> direto no programa ou em um arquivo de configurações, em vez de ser
> obrigado a passar o nome do arquivo como parâmetro, como nas soluções
> anteriores. Notas: certifique-se que os arquivos não estão sendo
> editados por mais ninguém durante o processo, de preferência com lock
> files. Outra: o rename() não funciona entre sistemas de arquivos,
> então crie o arquivo temporário de preferência no mesmo diretório do
> outro ou use File::Copy para uma solução realmente portátil.
> 
> 
> 
> Solução 5 (sem arquivos temporários)
> =============================
> 
> ----------8<-----------
> #!/usr/bin/env perl
> use strict;
> use warnings;
> use autodie;
> 
> open my $fh, '+<', 'arquivo.txt';
> 
> my @novas_linhas = ();
> my $i = 0;
> while ( my $linha = <$fh> ) {
>   if ($linha =~ s/^>.+$/>contig$i/ ) {
>     $i++;
>   }
> }
> continue {
>     push @novas_linhas => $linha;
> }
> 
> # volta ao inicio do arquivo,
> # sobrescreve tudo com as novas
> # e arranca fora (trunca) o que sobrar
> seek $fh, 0, 0;
> print $fh @novas_linhas;
> truncate $fh, tell($fh);
> close $fh;
> ---------->8-----------
> 
> Essa solução abre o arquivo em modo '+<' (update), o que te permite
> ler e escrever ao mesmo tempo no arquivo. Note que, se vc le e escreve
> AO MESMO TEMPO, o "stream de bytes" do arquivo muda o tempo todo, e
> você certamente vai se perder em relação ao ponto exato no arquivo em
> que seu handle está. Por isso, a solução é primeiro ler todo o arquivo
> em memória (ou ler somente as linhas que interessam, já com o conteúdo
> modificado, como fazemos acima), e só depois que processar todas as
> linhas, voltar ao início do arquivo e sobrescrever o conteúdo. De
> novo, faça lock do arquivo ou tenha certeza que ninguém vai editar o
> arquivo junto com seu programa.
> 
> Vale ressaltar que essa solução sem arquivo temporário só é
> recomendada se os arquivos forem pequenos e vc REALMENTE não puder
> usar arquivos temporários (por quê não poderia?), pois consome muito
> mais memória, é mais difícil de escrever, entender e manter, sem falar
> que não te dá a oportunidade de gravar uma cópia de segurança do
> arquivo original e pode confundir outros processos tentando ler o
> arquivo que você está editando.
> 
> Se, por outro lado, você puder GARANTIR que os tamanhos dos campos
> editáveis serão fixos (e substituidos pela mesma quantidade de bytes
> do mesmo tamanho), aí sim dá pra fazer algo bacana com o trio
> seek/read/print de forma eficiente e sem usar arquivos temporários.
> Mas isso normalmente só é verdade para arquivos binários.
> 
> Para mais informações: perldoc -f funcao (onde "funcao" seja uma das
> que foram usadas acima, tipo seek, tell e truncate).
> Para mais informações sobre lockfiles: perldoc -f flock
> 
> 
> 
> Bom, é isso. A solução 1 é a mais prática, mas não escala bem.
> Particularmente, prefiro a solução número 4, pelos motivos já citados.
> 
> Se essa foi realmente a sua pergunta, taí. Agora, se não foi, espero
> que pelo menos ajude alguém :)
> 
> Finalmente, mais uma dica: essas e muitas outras "receitas" podem ser
> encontradas no fantástico livro "Perl Cookbook" do Tom Christiansen e
> do Nathan Torkington. Foi um dos meus primeiros livros de Perl e um
> dos poucos que vira e mexe ainda consulto. Está todo muito bem
> dividido em grupos de problemas (string, arquivos, regex,...) e vc
> encontra rapidamente o que quer olhando o índice. Cada problema vem
> com a solução e uma discussão em cima do problema, de forma bastante
> didática.
> 
> 
> Versão Eletrônica (apenas Kindle):
> -----------------------------------------------
> 
> R$ 48,68 na amazon.com.br
> http://www.amazon.com.br/Perl-Cookbook-COOKBOOKS-ebook/dp/B0043GXMTS/ref=sr_1_1?s=digital-text&ie=UTF8&qid=1354942271&sr=1-1
> 
> USD$ 22,79 na amazon.com
> http://www.amazon.com/Perl-Cookbook-COOKBOOKS-ebook/dp/B0043GXMTS/ref=sr_1_1?ie=UTF8&qid=1354942175&sr=8-1&keywords=perl+cookbook+kindle
> 
> 
> Versão Eletrônica (vários formatos pra escolher):
> -----------------------------------------------------------------
> 
> USD$ 19,99* na loja da O'Reilly
> http://shop.oreilly.com/product/9780596003135.do
> 
> *USD$ o preço real da versão eletrônica é 39,99. Como vc faz parte de
> um grupo de usuários filiado à O'Reilly, é só usar o código de
> desconto "DSUG" e ganhar 50% de desconto para ebooks (40% para livros
> impressos).
> 
> R$48,49 na Cultura
> http://www.livrariacultura.com.br/scripts/resenha/resenha.asp?nitem=17405530&sid=12225113814128111046650811
> 
> 
> Versão Impressa:
> ------------------------
> 
> - não encontrei na Saraiva
> 
> - na Cultura tem sob encomenda, à R$144,40 (+frete)
> 
> - na Estante Virtual só tem 1 exemplar, à R$90,00 (+frete)
> http://www.estantevirtual.com.br/arkanthum/Tom-Christiansen-e-Nathan-Torkington-Perl-Cookbook-72690537
> 
> 
> Independente da sua escolha, é um livro que recomendo vivamente para a
> cabeceira de qualquer programador Perl, especialmente para quem está
> começando. Me ajudou bastante e tenho certeza que vai ajudar você
> também. Acredite: vale *cada* centavo.
> 
> 
> Qq dúvida, como sempre, estamos aí!
> 
> []s
> 
> -b
> _______________________________________________
> Rio-pm mailing list
> Rio-pm em pm.org
> http://mail.pm.org/mailman/listinfo/rio-pm
 		 	   		  

_______________________________________________
Rio-pm mailing list
Rio-pm em pm.org
http://mail.pm.org/mailman/listinfo/rio-pm 		 	   		  
-------------- Próxima Parte ----------
Um anexo em HTML foi limpo...
URL: <http://mail.pm.org/pipermail/rio-pm/attachments/20121209/8f88ff2d/attachment-0001.html>


Mais detalhes sobre a lista de discussão Rio-pm