<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>torradeira.net &#187; Perl</title>
	<atom:link href="http://torradeira.net/category/perl/feed/" rel="self" type="application/rss+xml" />
	<link>http://torradeira.net</link>
	<description>Milhares de dicas e tutoriais de informatica!</description>
	<lastBuildDate>Thu, 16 Sep 2010 23:42:24 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1</generator>
		<item>
		<title>Faça exames e simulados aqui no Blog</title>
		<link>http://torradeira.net/faca-exames-e-simulados-aqui-no-blog/</link>
		<comments>http://torradeira.net/faca-exames-e-simulados-aqui-no-blog/#comments</comments>
		<pubDate>Tue, 31 Jul 2007 00:12:05 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Adm. Linux]]></category>
		<category><![CDATA[AdSense]]></category>
		<category><![CDATA[Blog]]></category>
		<category><![CDATA[Dicas]]></category>
		<category><![CDATA[e-mail]]></category>
		<category><![CDATA[Leis de Informática]]></category>
		<category><![CDATA[Licenças]]></category>
		<category><![CDATA[Modems]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Perl]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Receitas de Bolo]]></category>
		<category><![CDATA[Samba]]></category>
		<category><![CDATA[Segurança]]></category>
		<category><![CDATA[Shell Script]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[warez]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[XML]]></category>

		<guid isPermaLink="false">http://torradeira.net/faca-exames-e-simulados-aqui-no-blog/</guid>
		<description><![CDATA[Bem, inspirado por outros sites que contém simulados e exames decide fazer um nova área no blog destinada a exames e simulados, alguns úteis e outros nem tanto.. como este primeiro que fiz para testar a funcionalidade do plugin e aceitação da idéia no blog. Para acessar o primeiro exame clique aqui Na próxima semana [...]]]></description>
			<content:encoded><![CDATA[<p>Bem, inspirado por outros sites que contém simulados e exames decide fazer um nova área no blog destinada a exames e simulados, alguns úteis e outros nem tanto.. como este primeiro que fiz para testar a funcionalidade do plugin e aceitação da idéia no blog.</p>
<p>Para acessar o primeiro exame clique <a href="http://torradeira.net/exame-de-conhecimento-tecnico-sobre-o-wordpress/">aqui</a></p>
<p>Na próxima semana provavelmente segunda vou colocar já a disposição um simulado para quem deseja fazer a prova LPI 101, o exame será feito por um profissional da área que já fez a prova e passou se certificando na LPI 101.</p>
<p>Aos poucos e conforme pedidos vou colocando novos exames e simulados!</p>
<p>até</p>
<p>Daniel</p>
<div id="crp_related"><h3>Artigos relacionados:</h3><ul><li><a href="http://torradeira.net/quer-fazer-um-simulado-para-as-provas-da-lpi/" rel="bookmark" class="crp_title">Quer fazer um Simulado para as provas da LPI</a></li><li><a href="http://torradeira.net/livro-para-estudar-para-certificacao-lpi-101-e-102/" rel="bookmark" class="crp_title">Livro para estudar para Certificação LPI 101 e 102</a></li><li><a href="http://torradeira.net/como-um-blogueiro-deve-saber-o-que-escrever/" rel="bookmark" class="crp_title">Como um blogueiro deve saber o que escrever</a></li><li><a href="http://torradeira.net/como-instalar-temas-e-plugins-no-seu-blog-wordpress/" rel="bookmark" class="crp_title">Como instalar temas e plugins no seu blog WordPress</a></li><li><a href="http://torradeira.net/6-plugins-para-aumentar-sua-produtividade/" rel="bookmark" class="crp_title">6 Plugins para aumentar sua produtividade</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://torradeira.net/faca-exames-e-simulados-aqui-no-blog/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Introducao ao Perl</title>
		<link>http://torradeira.net/introducao-ao-perl/</link>
		<comments>http://torradeira.net/introducao-ao-perl/#comments</comments>
		<pubDate>Mon, 22 Jan 2007 23:56:21 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Perl]]></category>

		<guid isPermaLink="false">http://torradeira.net/introducao-ao-perl/</guid>
		<description><![CDATA[Uma introdução ao Perl, uma linguagem de script presente em muitos sites da Internet, muito poderosa, multiplataforma e de rápido desenvolvimento O Perl é uma das linguagens mais usadas hoje em dia. PERL significa &#8220;Practical Extraction and Report Language&#8221; (linguagem prática de extração e relatório). Ela foi criada por Larry Wall para facilitar a manipulação [...]]]></description>
			<content:encoded><![CDATA[<p><font size="+1" color="#336699">Uma introdução ao Perl, uma linguagem    de script presente em muitos sites da Internet, muito poderosa, multiplataforma    e de rápido desenvolvimento</font></p>
<p>O Perl é uma das linguagens mais usadas hoje em dia.    PERL significa &#8220;Practical Extraction and Report Language&#8221; (linguagem    prática de extração e relatório). Ela foi criada    por Larry Wall para facilitar a manipulação de textos suprindo    as necessidades que o shell, awk e sed não conseguiam resolver. Perl    é a ferramenta para fazer o seu trabalho, de forma rápida e eficiente.</p>
<p><span id="more-24"></span></p>
<p>Apesar de ter sido originalmente escrita para manipulação    de texto, o fato de ter o código aberto e estar licenciada nos termos    da GPL, permitiu que se expandisse para as mais diversas áreas. Com Perl    é possível escrever ferramentas para administração    de sistema, servidores, daemons, CGIs, programar para X usando toolkits como    TK, Gtk+ e QT, escrever aplicativos Gnome e KDE, usar bibliotecas em C, interfaceamento    com banco de dados, entre outras coisas.</p>
<p>Uma das forças do Perl é a sua comunidade, que    assim como a do Linux colabora com o seu desenvolvimento e uso. O maior exemplo    é o CPAN (www.perl.com/CPAN/), Comprehensive Perl Active Network, que    é uma coleção de módulos e bibliotecas que permitem    desde codificar um cliente compatível com o ICQ até manipular    todo o funcionamento do servidor de web Apache. Antes de tentar reinventar a    roda, certifique-se de que alguém já não o tenha feito.</p>
<p>O objetivo deste artigo é introduzi-lo ao Perl, começando    pelo básico da linguagem até escrever uma pequena ferramenta de    administração de sistema. Não é necessário    conhecer Perl, mas um conhecimento básico de qualquer linguagem o ajudará    a entender melhor.</p>
<p><strong>Tipos de variáveis</strong></p>
<p>A maioria dos termos mais comuns será mantida em inglês    uma vez que será assim que você os achará na maior parte    da literatura sobre o assunto.</p>
<p>Os tipos de variáveis no Perl são: scalar, array,    hash e filehandle.</p>
<p><strong>$scalar</strong></p>
<p>O scalar (representado pelo $) é o tipo de variável    mais usada. Podendo representar:</p>
<ul>
<li>um número (ex: 1, -4, 10.897, -12e4),</li>
<li>uma string (ex: &#8220;Gooolll!!!&#8221;),</li>
<li>ou uma referência (mais sobre referências depois).</li>
</ul>
<p>Assim:</p>
<pre><font face="Courier">
$a = 4;			 	# Número 4
$b = "Erro número ";		# uma String</font></pre>
<p>Como o Perl diferencia um número de uma string? Depende    do contexto.</p>
<p>Assim:</p>
<pre><font face="Courier">print $b . $a;	#O '.' concatena duas strings</font></pre>
<p>resultando:</p>
<pre><font face="Courier">Erro número 4</font></pre>
<p>e:</p>
<pre><font face="Courier">print $b + $a;	#O '+' adiciona dois números</font></pre>
<p>resultando:</p>
<pre><font face="Courier">4</font></pre>
<p>No primeiro caso, o número 4 em $a é convertido    para</p>
<p>a string &#8220;4&#8243;. No segundo, a string &#8220;Erro número&#8221;    em $b é convertida para o número 0, já que não é    possível transformá-la em outro valor. No entanto, se a string    representar um número válido como &#8220;-3.14&#8243;, será    convertida para o número -3.14, se o contexto pedir um número.</p>
<p><strong>@array</strong></p>
<p>Uma array (ou matriz) é uma lista de scalares. Para criar    uma array (representada por @):</p>
<pre><font face="Courier">
@a = (1, 2, "mar",'); 	#Uma lista de três elementos
#(scalares), 2 números e 1 string</font></pre>
<p>Os parênteses têm um significado especial. Eles</p>
<p>colocam os scalares em um contexto de lista. No caso:</p>
<pre><font face="Courier">
@a = (2,');</font></pre>
<p>(2) é uma lista de um elemento, 2. Cada elemento de uma array pode ser acessado diretamente na forma $array[índice],    em que índice é a posição do elemento na lista. O primeiro elemento tem índice 0.</p>
<p>Analise a situação:</p>
<pre><font face="Courier">
$a = 33;		 #Um scalar
@a = ("trinta e três",'); #Uma  array de um elemento print $a;
print $a[0];
</font><font face="Courier">O que será impresso no primeiro print? E no segundo?
Resposta: 33 e "trinta e três".</font>
<font face="Courier">Porque o $a e $a[0] estão em "espaços"
diferentes dentro do Perl. Assim, você pode ter um scalar, uma array,
um hash, um filehandle e uma função com o mesmo nome. E uma não
interfere com a outra.</font>
<font face="Courier">Um recurso muito útil com os arrays é o slice
(fatia). </font>
O slice separa um pedaço de uma array.
<pre><font face="Courier">
@a = (1, 5, 4, "carro", "moto",');
#Uma array de 5 elementos
@b = @a[2..4];
#@b contém 4, "carro" e "moto"
</font></pre>
<p>Uma função muito usada quando se trabalha com<br />
arrays é o sort. O sort ordena alfabeticamente uma lista. No exemplo<br />
anterior:</p>
<pre><font size="2" face="Courier">
@a = sort(1, 5, 4, "carro", "moto",');
#Uma array de 5 elementos
@b = @a[2..4];
#@b contém 5, "carro" e "moto"</font></pre>
<p><strong>%hash</strong><br />
O hash(representado por %) é um caso especial de array.<br />
O hash é uma array cujo índice é uma string. Assim:</p>
<pre><font face="Courier">
%hash = (,');
#criada um hash vazio
$hash{'banana'} = "R$ 1,05";
#Item banana em hash com valor
#"R$ 1,05"
$hash{"maçã"} = "R$ 0,40";
#Idem para maçã
$hash{laranja} = "R$ 0,65";
#também válido, as aspas são
#opcionais</font></pre>
<p>Assim como a array, as variáveis<font face="Courier"><br />
$a, $a[0] e $a{0}</font> são todas diferentes e independentes.<br />
Um hash é na verdade uma array especial. Isso permite<br />
algumas coisas interessantes como:</p>
<pre><font face="Courier">@a = ("banana", 12, "uva", 40,');	</font></pre>
<pre><font face="Courier">#Uma array</font></pre>
<pre><font face="Courier">%frutas = @a;				</font></pre>
<pre><font face="Courier">#O conteúdo de @a foi convertido para</font></pre>
<pre><font face="Courier">#uma array</font></pre>
<pre><font face="Courier">print $frutas{uva};			</font></pre>
<pre><font face="Courier">#vai mostrar "40".</font></pre>
<p><strong>Filehandle</strong><br />
O filehandle é a forma que o Perl usa para se comunicar<br />
com o mundo externo. Não existe um símbolo especial para ele,<br />
por isso usa-se uma palavra em letras maiúsculas para evitar conflitos<br />
com palavras reservadas.<br />
Um filehandle pode ser a leitura de entrada, saída para<br />
a tela (STDIN, STDOUT), a leitura ou escrita de um arquivo ou mesmo um socket<br />
de rede (como uma conexão TCP/IP).<br />
<strong>Funções</strong><br />
As funções (ou subrotinas) no Perl são<br />
definidas pela declaração sub:</p>
<pre><font face="Courier">sub minha_primeira_funcao{</font></pre>
<pre><font face="Courier">#código da função vem aqui</font></pre>
<pre><font face="Courier">#....</font></pre>
<pre><font face="Courier">}</font></pre>
<p>Em que os <font face="Courier">{ } </font>definem um bloco que<br />
contém a subrotina. No Perl, não se definem<br />
os parâmetros das funções diretamente<br />
como em outras linguagens.<br />
Ao invés disso, o Perl define um array @_ que contém<br />
uma lista com os argumentos passados para a função.</p>
<p>Assim:</p>
<pre><font face="Courier">
minha_funcao(1234, $dado_a, $ar[6], $fruta{melao},');
#Chama-se    a funcao</font></pre>
<p>E na definição da função:</p>
<pre><font face="Courier">sub minha_funcao{</font></pre>
<pre><font face="Courier">$meu_dado_a = @[1]; </font></pre>
<pre><font face="Courier">$minha_frunta = @[3];</font></pre>
<pre><font face="Courier">}</font></pre>
<p>Ou, mais comum:</p>
<pre><font face="Courier">sub minha_funcao{</font></pre>
<pre><font face="Courier">($senha, $meu_dado_a, $param, $minha_fruta) = @_;</font></pre>
<pre><font face="Courier">#...</font></pre>
<pre><font face="Courier">}</font></pre>
<p>Cada item da array (@_) é copiado diretamente para o<br />
item correspondente na primeira lista.<br />
Para retornar um dado da função, usa-se o comando<br />
return.<br />
<strong>Referências</strong><br />
O conceito de referência é um pouco mais complicado<br />
de entender para quem está começando e/ou tem pouca experiência<br />
com programação. Uma referência "aponta" para<br />
outra variável. A referência contém a localização<br />
de outra variável. Nada melhor do que um exemplo para ajudar a entender:</p>
<pre><font face="Courier">$a = "Oi";	#Um scalar normal</font></pre>
<pre><font face="Courier">	$b = $a;	#O $b é uma referência para o $a</font></pre>
<p>O `' antes de uma variável serve para "extrair"<br />
sua referência. Assim:</p>
<pre><font face="Courier">print $$b;</font></pre>
<p>mostrará:</p>
<pre><font size="2" face="Courier">Oi</font></pre>
<p>Pode-se analisar como o scalar ($) referenciado por $b. Praticamente<br />
qualquer coisa pode ser referenciada: scalares($), arrays(@), hashes(%), filehandles<br />
ou mesmo funções(&#038;). Assim:</p>
<pre><font face="Courier">@array = ( 13, "carro", $a,'); </font></pre>
<pre><font face="Courier">#Uma array de 3 elementos</font></pre>
<pre><font face="Courier">$b = @array;				</font></pre>
<pre><font face="Courier">#$b é uma referência para</font></pre>
<pre><font face="Courier">#@array</font></pre>
<p>Assim, @$b é a array(@) referenciada por $b. Cuidado<br />
para não usar um tipo de variável diferente da referida pela referência,<br />
no caso usar um $ ($$b) ao invés de um @ (@$b). Isso causará um<br />
alerta ou mesmo erro na execução do programa.<br />
Pode não parecer óbvio o uso de referências,<br />
mas imagine uma array com 1MB de tamanho. Se você simplesmente copiá-la<br />
com:</p>
<pre><font size="2" face="Courier">@new_array = @old_array;</font></pre>
<p>você terá uma cópia idêntica de @old_array.<br />
Se @old_array tem 1MB, @new_array usará outro 1MB. Quando você<br />
passa parâmetros para uma função, os parâmetros são<br />
copiados para a array @_, a mesma situação ocorre. Se, ao invés<br />
de passar parâmetro por parâmetro, for passada uma referência,<br />
economiza-se memória e ganha-se velocidade:</p>
<pre><font face="Courier">@array_gigante = (,'); </font></pre>
<pre><font face="Courier">#Uma array</font></pre>
<pre><font face="Courier">#gigante</font></pre>
<pre><font face="Courier">funcao(@array_gigante,'); </font></pre>
<pre><font face="Courier">#passa uma referência da array</font></pre>
<pre><font face="Courier">sub funcao{</font></pre>
<pre><font face="Courier">$refarray = $_[1];	</font></pre>
<pre><font face="Courier">#Cópia da referência</font></pre>
<pre><font face="Courier">print @$refarray; </font></pre>
<pre><font face="Courier">#Usando a array normalmente</font></pre>
<pre><font face="Courier">print $$refarray[2];	</font></pre>
<pre><font face="Courier">#Ou o terceiro item</font></pre>
<pre><font face="Courier">}</font></pre>
<p><strong>Exemplo da vida real</strong></p>
<p>Nada melhor do que um exemplo útil para ver tudo funcionando<br />
junto. Vamos fazer um analisador para o arquivo de log de acesso de um servidor<br />
web.<br />
Existe um formato padrão para log de servidor de acesso.<br />
Esse formato é:</p>
<pre><font size="2" face="Courier">endereço ident user [data] "request"    status bytes</font></pre>
<p>Endereço: 	Endereço IP (mais comum) ou nome<br />
da máquina do cliente.<br />
Ident: 	Resposta do ident no cliente. Normalmente 	não<br />
usado (-).<br />
User: 	O nome do usuário, caso ele tenha se autenticado<br />
antes.<br />
Data: 	A data e a hora do acesso.<br />
Request: 	A linha de requisição enviada pelo<br />
cliente.<br />
Status: 	O status respondido pelo servidor.<br />
Bytes: 	A quantidade de bytes transferidos.<br />
Ex:</p>
<pre><font face="Courier">200.220.50.122 - gvtit [24/May/2000:08:19:04    -0300] "GET /it/index.html HTTP/1.0" 200 774</font></pre>
<p>O que queremos:<br />
1 - 	As páginas mais acessadas<br />
2 - 	Os endereços(usuários) que mais acessam<br />
o servidor<br />
3 - 	A quantidade total de bytes transferidos<br />
4 - 	A quantidade de bytes transferidos por página<br />
mais acessada.<br />
5 - A quantidade de bytes transferidos por clientes (endereços).<br />
Não nos interessa os campos ident, user e data. Interessam-nos<br />
apenas as entradas com status 200 (accepted).<br />
Outros tipos de resposta serão ignorados.<br />
Começando o programa:</p>
<pre><font face="Courier">#!/usr/bin/perl -w</font></pre>
<pre><font face="Courier">use strict;			</font></pre>
<pre><font face="Courier">my $file = $ARGV[0];	#arquivo a ser usado</font></pre>
<p>A primeira linha especifica que programa executará esse<br />
script.<br />
O -w especifica que o Perl deve ser mais rigoroso com os alertas,<br />
evidenciando potenciais erros.<br />
O "use strict" força o Perl a apenas aceitar<br />
variáveis locais, declaradas com o uso do "my". Isso ajuda<br />
a evitar que erros de digitação possam comprometer o programa.<br />
O "my" usado na declaração das variáveis<br />
as forçam a ser locais. Nesse caso, as variáveis declaradas fora<br />
de uma função não existirão dentro de uma função<br />
e variáveis declaradas dentro de uma função deixarão<br />
de existir quando a função termina.<br />
Assim, se existir uma variável $a fora de uma função<br />
e um $a dentro, elas serão independentes.<br />
A array @ARGV é uma variável especial. Ela contém<br />
os argumentos que foram passados pela linha de comando. Assim, estamos considerando<br />
que o primeiro argumento é o nome do arquivo a ser usado, contendo os<br />
logs.<br />
Continuando:</p>
<pre><font face="Courier">my $linha;</font></pre>
<pre><font face="Courier">open (LOG, "<$file",');	</font></pre>
<pre><font face="Courier">#abre-se o arquivo para leitura</font></pre>
<pre><font face="Courier">while ($linha = ){	</font></pre>
<pre><font face="Courier">#loop em cada linha</font></pre>
<pre><font face="Courier">#aqui elas serão processadas</font></pre>
<pre><font face="Courier">}			</font></pre>
<pre><font face="Courier">#fim do loop</font></pre>
<p>O open abre o arquivo para leitura (<) usando o filehandle<br />
LOG para designar o acesso a esse arquivo. A expressão<br />
$linha = , lê uma linha do arquivo. Os <><br />
são responsáveis por isso. Quando o arquivo terminar será<br />
devolvido o valor undef (indefinido) que é interpretado como falso pelo<br />
while, encerrando assim o loop.<br />
Dentro do loop while:</p>
<pre><font face="Courier">if ( $linha =~ /^(S+)s+S+s+S+s+[.*]s+"(.*)"s+(S+)s+(S+)$/    ){</font></pre>
<pre><font face="Courier">$ip = $1;</font></pre>
<pre><font face="Courier">$full_request = $2;</font></pre>
<pre><font face="Courier">$status = $3;</font></pre>
<pre><font face="Courier">$bytes = $4;</font></pre>
<p>Agora um pouco de expressões regulares. Expressões<br />
regulares são um dos recursos mais poderosos do Perl. Uma expressão<br />
regular tenta "casar" seu conteúdo com uma variável.<br />
No caso:</p>
<pre><font face="Courier">$linha =~ /^(S+)s+S+s+S+s+[.*]s+"(.*)"s+(S+)s+(S+)$/</font></pre>
<p>O sinal "=~" tenta casar o conteúdo de $linha<br />
com a expressão regular (entre //)<br />
Vamos desmontar a expressão regular(ER):<br />
/ 	#Especifica que é uma ER<br />
^ 	#Deve começar pelo primeiro caracter de $linha<br />
$ 	#Deve terminar exatamente no último caracter de<br />
$linha<br />
s 	#Um caracter de espaço (espaço ou tab)<br />
S	#Um caracter diferente de espaço<br />
.	#Um caracter qualquer<br />
+	#Significa um ou mais caracteres iguais ao precedente<br />
*	#	Nenhum ou mais caracteres iguais ao precedente<br />
()	#Gravar o conteúdo dentro dos parênteses<br />
(veja adiante)<br />
"	#O caracter `"`<br />
[	#O caracter `[`. `[` e `]`<br />
tem significado especial em ER<br />
Neste caso estamos checando se a $linha contém uma linha<br />
de log válida. Caso não contenha, capturaremos o erro em um else<br />
depois do bloco.<br />
Também aproveitamos para capturar as informações<br />
que nos interessam com o uso dos (). Serão criadas<br />
automaticamente as variáveis $1, $2, $3 e $4 correspondendo a cada<br />
(). Veja figura 1.<br />
Esta parte é bem direta. %contagem_ip usa o IP do log<br />
como chave (índice), %contagem_request usa o arquivo solicitado<br />
e o mesmo ocorre com a soma dos bytes.<br />
Ao terminar o loop do while, teremos todos os dados processados.<br />
Fechamos o filehandle e podemos começar a ordenação<br />
dos dados. Veja figura 2.<br />
<em>keys</em> é uma função especial para<br />
hashes. Ela gera uma array apenas com os índices<br />
(chaves) do hash.<br />
<em>sort</em> como vimos antes, ordena uma array alfabeticamente.</p>
<p>No entanto, podemos mudar a maneira de como ele ordena.<br />
Para isso especificamos uma função dentro de um BLOCO no sort<br />
com os valores $a e $b. $a e $b são dois elementos da array que está<br />
sendo ordenada. Essa função tem que retornar -1 se $a < $b,<br />
0 se $a == $b ou 1 se $a > $b. A função que faz isso é<br />
esta:</p>
<pre><font face="Courier">sub ordena_hash_numerica{</font></pre>
<pre><font face="Courier">	my ($a, $b, $hashref) = @_; #parâmetros de entrada</font></pre>
<pre><font face="Courier">	my $c = $$hashref{$a} <=> $$hashref{$b};</font></pre>
<pre><font face="Courier">	return $c;</font></pre>
<pre><font face="Courier">}</font></pre>
<p>No nosso caso $a e $b são chaves do hash %contagem_request<br />
e o que queremos é ordenar o valor dos hashes. Para podermos comparar<br />
o conteúdo do hash, tivemos que passar uma referência do hash.<br />
O operador <=> faz a tarefa que precisamos. Ele compara<br />
os valores à direita e à esquerda numericamente e retorna -1,<br />
0 ou 1 correspondentemente.<br />
O comando reverse é usado para reverter a ordem de uma<br />
array ou lista. Assim teremos os acessos da ordem do maior para o menor, que<br />
é a desejada. Depois de termos as chaves ordenadas por ordem de acesso,<br />
pegamos as dez primeiras que nos interessam.<br />
Para visualizá-las:</p>
<pre><font face="Courier">print "Páginas mais acessadas:

#	acessos	bytes	Páginas
";</font></pre>
<pre><font face="Courier">$count = 0;</font></pre>
<pre><font face="Courier">foreach $request_url (@top_ten){</font></pre>
<pre><font face="Courier">			$count++;	#adiciona 1 ao $count</font></pre>
<pre><font face="Courier">			print "$count	$contagem_request{$request_url}	";</font></pre>
<pre><font face="Courier">			print "$bytes_request{$request_url}	$request_url
";</font></pre>
<pre><font face="Courier">}</font></pre>
<p>Finalizando um loop especial é o foreach. Ele executa<br />
o BLOCO uma vez para cada elemento da array @top_ten. No entanto, a cada interação,<br />
$request_url recebe um elemento de @top_ten. Para completar, esse processo de<br />
ordenação e visualização tem de ser repetido para<br />
cada item (hash) que queremos mostrar.<br />
Veja a listagem completa na figura 3.<br />
Note as alterações finais no programa. A primeira<br />
foi a remoção do open do arquivo e o uso do <>. O loop usando<br />
como parâmetro o <> é um caso especial no Perl. Nesse caso,<br />
o Perl irá abrir para leitura todos os arquivos especificados na linha<br />
de comando (ex: loganaliser log log.1 log.2). Caso nenhum arquivo tenha sido<br />
especificado, a leitura será feita da entrada padrão (STDIN).<br />
Isso possibilita, entre outras coisas, o uso de "pipes" no programa<br />
(ex. cat arq | loganaliser).<br />
Outra alteração é a criação<br />
da função ordena_e_mostra, que recebe duas referências de<br />
hashes como parâmetros. Isso possibilita que ela possa ser usada genericamente.<br />
Note também que retiramos as arrays usadas e colocamos tudo na mesma<br />
linha. O slice [0..9] depois do sort e reverse, na função ordena_e_mostra,<br />
funciona por uma simples razão: uma lista especificada entre parênteses<br />
é um array sem a variável (sem nome e sem o `@`).<br />
Antes de mais nada, o Perl é a ferramenta para que você<br />
tenha o seu trabalho resolvido. Com esse exemplo é possível perceber<br />
o seu poder. Mas não para por aí. Existem muitos programas feitos<br />
em Perl, como clientes de e-mail e até mesmo um servidor Radius, o radiator,<br />
essencial em um provedor de internet.<br />
<strong>para saber mais</strong><br />
<a href="http://www.perl.com/">www.perl.com</a></p>
<p><a href="http://www.perl.org/">www.perl.org</a></p>
<p><a href="http://www.perl.com/CPAN">www.perl.com/CPAN/</a></p>
<p>No seu computador: man perl</p>
<p>Livros:</p>
<p>Learning Perl - Schwartz &#038; Christiansen -<br />
Ed. O'Reilly</p>
<p>Programming Perl - Wall - Ed. O'Reilly<br />
Figura 1</p>
<pre>if ($status == 200){
#Extrai a URL:
$full_request =~ /S+s+(.*)s+S+/;

$request = $1;

#Garante que o valor é numérico
#Caso o usuário aborte, é colocado "-" no lugar
if ($bytes eq "-"){
$bytes = 0;
}
$contagem_ip {$ip}++;                     #Faz a contagem de
$contagem_request {$request}++;           #acessos
$bytes_ip {$ip}    += $bytes;             #E a quantidade de bytes
$bytes_request {$request}    += $bytes;   #transferidos
$total    += $bytes;                      #O total

}else{          #Aqui contabilizamos o número
$nao_200++;   #de páginas com status diferente de 200
}
}else{            #E o número de erros
$erros++;       #Erro são as linhas que não "casam"
}                 #com a Expressão Regular
}                 #Fim do Loop While
close(LOG,');       #Fecha o LOG

Figura 2
<pre>@keys           = keys %contagem_request;    #As chaves índices) do hash
@sorted_keys    = reverse sort{
ordena_hash_numerica($a, $b, \%contagem_request,');
}@keys;                                      #ordena @keys numericamente
@top_ten        = @sorted_keys [0..9];       #Os 10 primeiros elementos</pre>
<p>Figura 3</p>
<pre>#!/usr/bin/perl -w
use strict;
# declaração das variáveis
my ($ip, $full_request, $status, $bytes,');
my ($request, $total, $nao_200, $erros,');
my (%contagem_ip, %contagem_request, %bytes_ip, %bytes_request,');
while (<>){    #loop em cada linha
if ( /^(S+)s+S+s+S+s+[.*]s+"(.*)"s+(S+)s+(S+)$/ ){
$ip      = $1;
$full_request = $2;
$status    = $3;
$bytes    = $4;
if ($3 == 200){
#Extrai a URL:
$full_request =~ /S+s+(.*)s+S+/;
$request = $1;
#Garante que o valor é numérico
#Caso o usuário aborte, é colocado "-" no lugar
if ($bytes eq "-"){
$bytes = 0;
}
$contagem_ip {$ip}++;                     #Faz a contagem de
$contagem_request {$request}++;           #acessos
$bytes_ip {$ip}    += $bytes;             #E o a quantidade de bytes
$bytes_request {$request}    += $bytes;   #transferidos
$total    += $bytes; #O total
}else{                                      #Aqui contabilizamos o número
$nao_200++;                               #de páginas com status diferente de 200
}
}else{                                        #E o número de erros
$erros++;                                     #Erro são as linhas que não "casam"
}                                             #com a Expressão Regular
}                                               #Fim do Loop While
#As 10 páginas (arquivos) mais acessadas
print "Páginas mais acessadas:

#	acessos	bytes	Páginas
";
ordena_e_mostra(\%contagem_request, \%bytes_request,');
#Os 10 clientes (usuários) que mais acessam
#Não considera proxies.
print "
Clientes que mais acessam:

#	acessos	bytes	Cliente
";
ordena_e_mostra(\%contagem_ip, \%bytes_ip,');
print "
Dados Finais:
";
print "Erros:  $erros
";
print "Não 200: $nao_200
";
print "Total:  $total
";
#ordena e mostra os dados
sub ordena_e_mostra{
my ($ref_a, $ref_b)=@_;
my $count = 0;
foreach $item ((reverse sort {$$ref_a {$a} <=> $$ref_a {$b}} keys %$ref) [0..9]){
$count++;    #adiciona 1 ao $count
print "$count	";    #Mostra os dados
print "$$ref_a {$item}	";    #O item principal
print "$$ref_b {$item}	";    #Item secundário
print "$item
";    #O nome do item
}
}</pre>
</pre>
</pre>
<div id="crp_related"><h3>Artigos relacionados:</h3><ul><li><a href="http://torradeira.net/estruturas-complexas-em-perl/" rel="bookmark" class="crp_title">Estruturas complexas em perl</a></li><li><a href="http://torradeira.net/programando-em-shell-script/" rel="bookmark" class="crp_title">Programando em Shell Script</a></li><li><a href="http://torradeira.net/atualizando-o-kernel/" rel="bookmark" class="crp_title">Atualizando o kernel</a></li><li><a href="http://torradeira.net/mysql-velocidade/" rel="bookmark" class="crp_title">Mysql: velocidade</a></li><li><a href="http://torradeira.net/o-kernel-do-linux/" rel="bookmark" class="crp_title">O kernel do Linux</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://torradeira.net/introducao-ao-perl/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Estruturas complexas em perl</title>
		<link>http://torradeira.net/estruturas-complexas-em-perl/</link>
		<comments>http://torradeira.net/estruturas-complexas-em-perl/#comments</comments>
		<pubDate>Mon, 22 Jan 2007 23:38:26 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Perl]]></category>

		<guid isPermaLink="false">http://torradeira.net/estruturas-complexas-em-perl/</guid>
		<description><![CDATA[Dando prosseguimento ao artigo &#8220;Introdução ao Perl&#8221;, na revista No 07, iremos nos aprofundar um pouco mais no uso do Perl. Ao longo dos próximos artigos iremos escrever uma agenda de contatos simples, utilizando vários recursos do Perl. O objetivo desse artigo será entender como funcionam estruturas de dados complexos no Perl. Nessa agenda nós [...]]]></description>
			<content:encoded><![CDATA[<p>Dando prosseguimento ao artigo &#8220;Introdução ao Perl&#8221;, na revista No 07, iremos nos aprofundar um pouco mais no uso do Perl. Ao longo dos próximos artigos iremos escrever uma agenda de contatos simples, utilizando vários recursos do Perl. O objetivo desse artigo será entender como funcionam estruturas de dados complexos no Perl.</p>
<p>Nessa agenda nós desejamos guardar os seguintes dados:</p>
<p>Nome da pessoa, Endereço, Telefone, Aniversário, Ocupação, Outras Notas.</p>
<p><span id="more-21"></span></p>
<p>Precisamos agora definir como armazenar esses dados. As variáveis do tipo scalar não nos interessam. Uma variável desse tipo pode armazenar apenas um dado de cada vez. Para os dados que queremos, precisaríamos ter para uma pessoa: <font face="courier">$nome, $endereco, $telefone, $aniversario, $ocupacao, $outras</font></p>
<p>O primeiro problema que surge é como armazenar dados de diversos contatos juntos. Poderíamos ter variáveis scalares como $joao_endereco, $maria_aniversario e assim por diante. Mas isso não resolve o problema, pois precisaríamos saber, na hora de escrever o programa, o nome de todas as pessoas que estariam nessa agenda.</p>
<p><strong>%HASHES</strong> &#8211; A variável hash é um tipo especial de variável encontrada em poucas linguagens. Uma hash associa vários nomes a um valor (scalar) cada. Podemos considerar que cada variável %hash é um minibanco de dados. Com a hash podemos ter uma estrutura um pouco melhorada dos dados: <font face="courier">%endereco, %telefone, %niversario, %ocupacao, %outras</font></p>
<p>E podemos adicionar um contato da seguinte forma:</p>
<pre><font face="courier">

$endereco{`Carlos'}    = "R. 13 de Maio, 1450";
$telefone{`Carlos'}    = "555-5555";
$aniversario{`Carlos'} = "28/02";
$ocupacao{`Carlos'}    = "Dentista";
$outras{`Carlos'}      = "Primo do Mario";

</font></pre>
<p>Note que excluímos o nome, pois estamos usando-o como a &#8220;chave&#8221; dos hashes. Note também que estamos usando o simbolo `$&#8217; nas variáveis. Isso indica que estamos trabalhando com os elementos das hashes. A variável $endereco{`Carlos&#8217;} é um elemento de %endereço.</p>
<p>Existe outro motivo para se usar o `$&#8217;. Cada elemento de um hash é um scalar. Dessa forma, pode ser armazenado strings, números e referências, da mesma forma que se faz com uma variável scalar. No entanto, os nomes das variáveis são independentes. Se tivermos uma variável chamada $endereço ela será diferente de $endereço{Carlos}. A última, apesar de ser tratada como scalar, se refere ao elemento `Carlos&#8217; do hash %endereço.</p>
<p>Note que a chave de cada item é uma string (não confunda com $scalar). O uso dos `&#8217; é opcional, caso a string não contenha espaços ou caracteres especiais. Assim, podemos ter:</p>
<pre><font face="courier">

$endereco{Carlos}, $endereco{`João Cunha'}, $endereco{$nome}.

</font></pre>
<p>No último caso, assume-se que $nome contém a string desejada. O uso de hashes resolve pequenos problemas como esses.</p>
<p>Imagine que o Carlos tenha um celular e eu queira o número do celular na agenda.</p>
<p>Um novo hash %telefone_celular resolveria, mas imagine que o Marcos tenha 1 celular, 1 telefone residencial, 2 telefones no trabalho e mais 1 para fax. Nesse caso o simples uso do hash já não fica tão fácil.</p>
<p><strong>Referências</strong></p>
<p>Um scalar pode armazenar uma referência para uma variável. Uma referência é a posição interna no programa em Perl, onde uma variável se encontra. Dessa forma, uma referência &#8220;aponta&#8221; para uma variável. Assim:</p>
<pre><font face="courier">

$a = "oi";
$b = $a;

</font></pre>
<p>$b contém a posição interna da variável $a. A barra `&#8217; indica que queremos a referência da variável $a e não o seu valor. Se tentarmos ver o resultado: print $b; teremos algo como: SCALAR(0x80e2eec), que somente interessa ou faz sentido para o interpretador Perl. Referências valem para qualquer tipo de variável, assim:</p>
<pre><font face="courier">

%idade = (
Carlos => 26,
Amanda => 21
,');
@nomes = (`Carlos', `João', `Amanda',');
$a = \%idade;
$b = @nomes;
$c = $idade{Carlos};
$d = $nomes[1];

</font></pre>
<p>Note que os parênteses foram usados para declarar os valores de %idade e @nomes. No caso da hash %idade isso é possível porque um hash é visto internamente pelo Perl como uma array, com a diferença de que cada elemento tem uma &#8220;chave&#8221; (ou nome) associado a ele. Por isso, é comum encontrar o nome &#8220;Associative Array&#8221; se referindo ao hash.</p>
<p>As variáveis $a e $b contêm respectivamente referências para um hash e um array e as variáveis $c e $d para dois elementos do hash e array, ou seja, referências para variáveis scalares.</p>
<p>As referências podem ser usadas no lugar das variáveis originais às quais elas se referem. Para isso usamos uma técnica chamada de desreferenciamento. Para isso basta especificar o tipo de variável que estamos desreferenciando com o seu símbolo na frente.</p>
<p>Assim, %$a pode ser usado da mesma maneira que se usuaria %idade. $$a{Amanda} se refere ao elemento `Amanda&#8217; de %idade. $$c se refere ao elemento `Carlos&#8217;. No caso de $c, não é possível desreferenciá-lo com % como em %$a, porque o tipo de referência que ele possui não é para um hash, mas sim para um scalar (mesmo que esse scalar seja um elemento de um hash).</p>
<p>Por outro lado, o Perl nos permite associar elementos de uma array ou hash diretamente pela referência, sem precisar desreferenciá-la. Nesse caso:</p>
<p><font face="courier">$a->{Carlos} é a mesma coisa que $idade{Carlos} ou $$c</font></p>
<p>e</p>
<p><font face="courier">$b->[1] é a mesma coisa que $nomes[1]ou $$d</font></p>
<p>Voltando à agenda de contatos, podemos ter uma idéia de como resolver a questão de vários telefones para um mesmo contato. Podemos usar referências de hash. Considerando que o Carlos tenha 3 telefones, podemos colocar todos os telefones em um lista, ou array, e guardar a sua referência:</p>
<pre><font face="courier">

@telefones_do_Carlos=(`55-5555',`911-3456',`33-2323',');
$telefone{Carlos} = @telefones_do_Carlos;

</font></pre>
<p>Agora os elementos de %telefone são na verdade referências para @arrays, que contém os dados. Para obtermos o segundo telefone da lista (o primeiro tem o índice 0), podemos fazer algo como:</p>
<pre><font face="courier">

print ${$telefone{Carlos}}[1];

</font></pre>
<p>Note que os primeiros `{}&#8217; servem para especificarmos que estamos nos referindo a $telefone{Carlos} e não apenas $telefone. Se tivermos:</p>
<pre><font face="courier">

$ref = \%telefone;

</font></pre>
<p>O mesmo elemento poderia ser acessado:</p>
<pre><font face="courier">

${$$ref{Carlos}}[1];
${$ref->{Carlos}}[1];
$$ref{Carlos}->[1];

</font></pre>
<p>ou para simplificar:</p>
<pre><font face="courier">

$ref->{Carlos}->[1];
</font></pre>
<p>pode-se ler isso como: o segundo elemento da array referenciada pelo elemento `Carlos&#8217; da hash referênciada por $ref. Você deve ter notado que essa forma de trabalhar, apesar de mais eficiente, nos traz de volta ao problema original.</p>
<p>Precisaríamos criar várias arrays como @telefones_do_Carlos para podermos referenciá-las em %telefone. Note que se @telefones_do_Carlos for alterado, as referências em $telefone{Carlos} também serão.</p>
<p><strong>Variáveis Anônimas</strong></p>
<p>Isso nos leva a um conceito muito interessante no Perl, chamado de variáveis anônimas. Como o nome indica, uma variável anônima é uma variável que não possui nome definido.Para isso, ela já é criada na forma de referência.</p>
<pre><font face="courier">

$array_ref = [ 1, 3, `oi', 45 ];
$hash_ref  = {
Laranja => '12,50',
Maçã    => `7,60'
};
$scalar_ref = "Uma string";

</font></pre>
<p>Ou seja, os `[]&#8216; criam uma array e passam sua referência para $array_ref, os `{}&#8217; fazem a mesma coisa com um hash. No caso do scalar, não existe um símbolo especial como esses, então pegamos a referência diretamente da string com o `&#8217;. É importante notar que a única forma de existência de uma variável anônima se dá através de sua referência. Se todas as suas referências forem eliminadas (associando um outro valor a $array_ref, por exemplo), a variável anônima é destruída e apagada da memória.</p>
<p>Podemos reescrever o hash de telefone da seguinte forma:</p>
<pre><font face="courier">

$telefone{Carlos}=[`55-5555',`911-3456',`33-2323'];

</font></pre>
<p>Assim, $telefone{Carlos} contém uma referência para uma array (que contém os telefones).Mas se é possível facilitar a escrita dos telefones, também podemos facilitar para todos os dados do contato:</p>
<pre><font face="courier">

$contato = {
nome        => `Carlos',
endereco    => ` R. 13 de Maio, 145',
aniversario => "28/02",
ocupacao    => "Dentista",
outras      => "Primo do Mario",
telefone    => [`55-5555',`911-3456',`33-2323']
}

</font></pre>
<p>Dessa forma, sempre que quisermos nos referir ao Carlos só será necessária a variável $contato. Vamos expandindo a capacidade de dados armazenados na nossa agenda:</p>
<pre><font face="courier">

$contato = {
`Carlos Rocha' => {
endereco     => {
Residencial => {
endereco => `R. 13 de Maio, 145',
CEP      => `',
cidade   => `São Paulo'
},
Comercial   => {
endereco => `Av. Silva Jardim, 5445',
CEP      => '54.376-000,
cidade   => `Florianópolis'                          }
},                                     aniversario => "28/02",
ocupacao => ["Dentista", "Estudante de     Administração"]
outras      => "Primo do Mario",
telefone    => {
`555-5555'  => `comercial',
`555-5513'  => `fax',
`9114-3456' => `celular',
`333-2323'  => `residencial'
}
}
};

</font></pre>
<p>Mantivemos em letras minúsculas os campos não variáveis.</p>
<p>$contato é uma referência para um hash, onde cada &#8220;chave&#8221; é o nome da pessoa a que nos referimos.</p>
<p>Cada elemento (com o nome do contato) é uma referência para uma estrutura de dados desse contato.</p>
<p>Além do elemento `Carlos Rocha&#8217;, podem haver mais contatos na mesma hash referenciada por contato. Em quase todos os elementos, usamos hashes para montar as estruturas. O motivo é que dessa forma podemos facilmente expandir as informações ilimitadamente.</p>
<p>Se o Carlos comprar uma casa na praia e quisermos colocá-la na agenda, basta colocar um novo elemento `Casa de Praia&#8217; em $contato->{`Carlos Rocha&#8217;}->{endereco}.</p>
<p>Ainda usamos uma array no campo `ocupacao&#8217; porque não nos interessa saber mais informações sobre cada ocupação.</p>
<p>Embora o exemplo que estamos usando é o de uma agenda simples de contato, as técnicas vistas aqui podem ser empregadas em estruturas muito mais complexas para diversos tipos de aplicações.</p>
<p>Para finalizar, vamos escrever uma pequena sub-rotina que mostra na tela os contatos.</p>
<p>No próximo artigo abordaremos como armazenar e recuperar esses dados em arquivos.</p>
<hr noshade="noshade" /><strong>função.pl</strong></p>
<pre><font face="courier">

sub mostra_contatos{
#$contato é o parâmetro passado para a função
my ($contato) = @_;
#Vamos predeclarar cada variável antes de usá-la
my ($nome, $ocupacao, $tipo_endereco, $telefone,');

# O foreach executa um loop para cada item da array à direita
# no caso (keys(%$contato)), gravando o valor atual na variável
# $nome
# Primeiro desreferenciamos $contato para ser tratado como um hash
# e usamos a função keys() para gerar uma lista com todas as chaves
# da hash %$contato
foreach $nome (keys(%$contato)){
print "Nome: $nome
";
print "Ocupação:
";
#agora desreferenciamos a array anônima de ocupação
foreach $ocupacao (@{$contato->{$nome}->{ocupacao}}){
print "	$ocupacao
";
}
print "Aniversário: " . $contato->{$nome}->{aniversario} . "
";
print "Endereços:
";
#Agora para a hash referenciada em endereco
foreach $tipo_endereco (keys(%{$contato->{$nome}->{endereco}})){
print "	$tipo_endereço:
";
print "		Endereço: " . $contato->{$nome}->{endereco}->{$tipo_endereco}->{endereco} . "
";
print "		CEP     : " . $contato->{$nome}->{endereco}->{$tipo_endereco}->{cep} . "
";
print "		Cidade  : " . $contato->{$nome}->{endereco}->{$tipo_endereco}->{cidade} . "
";
}

#Finalmente para os telefones
print "Telefones:
";
foreach $telefone (keys(%{$contato->{$nome}->{telefone}})){
print "	" . $contato->{$nome}->{telefone}->{$telefone} . ": $telefone
";
}

print "Outras Informações:
" . $contato->{$nome}->{outras} ."
";
}
#Agora para separar entre os contatos
print "-"x40;
}

</font></pre>
<div id="crp_related"><h3>Artigos relacionados:</h3><ul><li><a href="http://torradeira.net/introducao-ao-perl/" rel="bookmark" class="crp_title">Introducao ao Perl</a></li><li><a href="http://torradeira.net/curso-de-shell-aula-1/" rel="bookmark" class="crp_title">Curso de Shell &#8211; Aula 1</a></li><li><a href="http://torradeira.net/mysql-velocidade/" rel="bookmark" class="crp_title">Mysql: velocidade</a></li><li><a href="http://torradeira.net/programando-em-shell-script/" rel="bookmark" class="crp_title">Programando em Shell Script</a></li><li><a href="http://torradeira.net/trabalhando-com-pacotes-rpm/" rel="bookmark" class="crp_title">Trabalhando com pacotes RPM</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://torradeira.net/estruturas-complexas-em-perl/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

