palestra: Descubra o poder do Perl


VocÍ quer aprender mais via email sobre o uso do Unix/Linux, CGI-scripts, etc.? Veja algumas dicas do boletim ViaLinuxis.
autor e speaker: Jorge Kinoshita. apresentação: 21 de Julho de 1999  local: Sucesu, rua Tabupuã, 627; 18:00h.
 

1. Introdução.

O que se espera desta palestra?

Um pensamento de quem conhecelinguagens como C, Pascal, Basic e Fortran pode ser o seguinte:
"todas as linguagens são iguais e baseiam-se nos mesmos princípios: todas possuem estrutras do tipo if-then-else, while, declaração de rotinas, etc.
Para mim deve ser extremamente fácil aprender uma outra linguagem como o Perl (pois dizem que se parece com o C).
O que me intriga (e por isso estou nesta palestra) é o seguinte: será que o Perl possui recursos além desta programação tradicional que me pode ser interessante? Aliás, ainda não sei por quê, mas o Perl é muito usado para escrever CGI-scripts. Por que não escolheram outra linguagem? O que torna o Perl uma linguagem peculiar?
 

Minha visão pessoal sobre o Perl comparando com outras linguagens.

Conheço várias linguagens de programação: C, C++, Java, JavaScript, Smalltalk, Prolog, etc. Podemos dizer que algumas linguagens tiveram seu momento na história das linguagens apresentando uma nova visão de como programar: entre elas destaco o Fortran que foi uma das primeiras linguagens a apresentar o computador através de estruturas bem padronizadas e muito mais fáceis de usar que o Assembly, o Smalltalk que foi uma das primeiras a apresentar de forma bem organizada a idéia de programação por objetos e o Prolog que vê um programa como uma declaração de uma sequencia de cláusulas que podem assumir verdadeiro e falso. Talvez o Java que se propõe a ser uma linguagem que roda em uma máquina virtual Java disponível em diversas plataformas pela Sun; entretanto o Java não propõe nenhum novo paradigma de programação.
O Perl é ao meu ver uma dessas linguagens revolucionárias que tornam a programação muito mais rápida. Entretanto ao contrário do Samlltalk e do Prolog que buscaram um paradigma totalmente orientado a objetos ou um paradigama orientado à lógica, o Perl não se preocupa em estabelecer um paradigma de programação. A idéia de seu idealizador "Larry Wall" é a seguinte: construir uma linguagem que seja prática de usar. Na visão de Larry Wall pode-se fazer a mesma coisa de diversas formas e o Perl é uma linguagem que dá muita liberdade ao programador (vide comando if x unless == if not).  Na versão corrente do Perl é possível usar ou não programação orientada à objetos (como o C++) (Eu pessoalmente considero o Smalltalk bem superior ao C++ mas a questão de fato não é se uma linguagem de programação deve ser fiel ou não a um paradigma. A questão é: será que a linguagem é confortável ao programador? Por exemplo: em C, é possível se acessar uma posição indevida da memória devido ao mal uso do índice de uma array, ao mal uso de um pointer, etc. Esta preocupação é um detalhe que desaparece nas linguagens mais modernas que se encarregam de fazer a alocação da memória de forma conveniente e segura.)
O que eu pessoalmente constato é que a praticidade oferecida pelo Perl torna a programação muito mais rápida que aquela oferecida por outras linguagens (ao meu ver, incluindo o Smalltalk e o Prolog ).
O objetivo desta palestra é apresentar os motivos que permitem se escrever programas em Perl de forma mais rápida que em outras linguagens.
 
 

2. O que torna a escrita de programas em Perl mais rápida do que em outras linguagens?

Estou listando as respostas colocando em ordem decrescente de importância.
 

2.1 Uso de expressões regulares.

(obs: já presente no antecessor do Perl: o AWK. Para quem está acostumado com o Unix, lembrar do grep e do lex(flex no GNU) ).

O que são expressões regulares?

É um padrão - um formato - que se casa (match) em uma string. O matching pode ocorrer (ser verdadeiro) ou não (ser falso) dependendo do padrão e da string. É possível substituir as partes que foram encaixadas por outras strings.

Exemplos:

\d+ = uma sequencia de dígitos
\w+\d = uma sequencia de letras ou dígitos (uma ou mais) seguida de um dígito.
\w+(\d|\.) = uma sequencia de letras ou dígitos seguida de um digito ou de um ponto.
nome:\s*.* = a palavra nome: seguida de zero ou mais espaços (os espaços são opcionais) seguido de qualquer caracter zero ou mais vezes.
nome:\s*(.*) = igual ao anterior, mas os parênteses servem para capturar em $1 este valor.
etc.

\w == [a-zA-Z0-9_]
\d == [0-9]
\s == [ \r\t\n\f]
 
 

Como o Perl usa expressões regulares?

Em comandos como:

ex1: Matching


if ($linha =~ /nome:\s*(.*)/) {
$nome = $1; # extrai o nome
}

ex2: substitui uma sequencia de digitos pela palavra DIGITO (faz isto apenas uma vez)



$linha =~ s/\d+/DIGITO/;


Para:

$linha = "asdf 234 asdf 1234 ";

após a execução do comando temos:

$linha == 'asdf DIGITO asdf 1234 '
 
 

ex3: substitui em todas as ocorrências



$linha =~ s/\d+/DIGITO/g;


resultado para $linha = "asdf 234 asdf 1234 ":
'asdf DIGITO asdf DIGITO '

ex4: dentro de um split

O Perl trabalha com listas e é extremamente simples transformar strings em listas e vice-versa:


@gomos = split(/\s+/,$linha);


Para:
$linha = "asdf 234 asdf 1234 ";

temos:
0 'asdf'
1 234
2 'asdf'
3 1234
 

ex5: qual seria o resultado de


@gomos = split(/\d+/,$linha);


0 'asdf '
1 ' asdf '
2 ' '
 

Problema 1: Substituir um \r \n (texto no Microsoft) por apenas \n (texto no Unix) dentro de um arquivo. Uma solução simples é apenas retirar os \r de todas as linhas.

Para meditar: pense em como você resolveria este problema em C.
Em C você teria que:
  fechar o arquivo de saída (a menos que fosse o STDOUT).
 
Solução 1 em Perl:


#!/usr/bin/perl
while (<>) {
s/\r//;
print;
}


Observação: a variável $_ é usada como default.
 
Solução 2 em Perl:


perl -p -e 's/\r//' $1

Problema 2: suponha um arquivo que contenha como primeira palavra uma determinada característica e após vem o conteúdo desta característica. Quero separar a característica e o contéudo.

Exemplos de arquivos de entrada
ex1:

nome: Jorge K.
formação: engenharia
 
 

Obs: as palavras nome: e idade podem aparecer em qualquer posição dentro do arquivo e são tratados como palavras reservadas.
Exercício: imagine como você resolveria este problema em C ou Pascal.

Solução em Perl:


while(<>) {
if (/\s*(\w+)/) {
$caracteristica = $1;
$conteudo = $';
}
}


Observação:

2.2. O hash

O uso de arrays é extremamente comum em linguagens convencionais:
ex: a[0], nome[4];
Uma hash é como uma array, mas ao invés do índice ser um número é uma string.
Através de uma hash já temos então um banco de dados simples: temos uma chave e o conteúdo da chave.
Exemplos:


$formacao{"Jorge"} = "engenheiria eletronica, mod: digital";
$turma{"Jorge"} = 1985;


Ex1: retirar elementos repetidos de um arquivo.
Imagine um arquivo que contém um nome em cada linha. Quero gerar um arquivo de nomes mas sem nomes repetidos.

Exercício: imagine a solução em C, Pascal ou Basic.
Solução em Perl:



while (<>) {
chomp;
$lixo{$_} = 1;
}
foreach $a (keys %lixo) {
print $a . "\n";
}


hashs mapeadas em dbms.

No mundo Unix é possível se ter arquivos que vamos chamar de "bancos de dados leves". São arquivos que associam uma chave a um conteúdo. Um exemplo é o GDBM. É possível mapear uma hash em um GDBM de forma extremamente simples.
Exemplo:



#!/usr/bin/perl
use GDBM_File;

dbmopen(%lixo, "lixo", 0644);

while (<>) {
chomp;
$lixo{$_} = 1;
}
foreach $a (keys %lixo) {
print $a . "\n";
}
dbmclose(%lixo);


 

Neste caso, é criado o arquivo lixo que pode ser manipulado posteriormente como uma hash em outro script Perl.
 
 

2.3. A interface com o ambiente Unix

No Unix é comum que os comandos envolvam troca de strings. O perl pode se comunicar com o Unix trocando strings.
Por exemplo: capturar uma string que vem como retorno do comando ps.

Ilustração: O comando ps no shell
[j@localhost art]$ ps
PID TTY STAT TIME COMMAND
400 1 S 0:00 (login)
401 2 S 0:00 /bin/login -- j
445 1 S 0:00 (bash)
459 1 S 0:00 (startx)
460 1 S 0:00 (xinit)
463 1 S 0:00 /usr/X11R6/bin/afterstep
474 1 S 0:00 /usr/X11R6/bin//Animate 7 4 /usr/share/afterstep/base.8bpp 0
475 1 S 0:00 /usr/X11R6/bin//Wharf 9 4 /usr/share/afterstep/base.8bpp 0 8
477 1 S 0:00 /usr/X11R6/bin//Pager 11 4 /usr/share/afterstep/base.8bpp 0
478 1 S 0:00 asclock -shape -24
492 p3 S 0:00 bash
494 1 S 0:02 emacs -geometry 128x40+0+20
574 p3 S 0:00 man perl
575 p3 S 0:00 sh -c (cd /usr/man ; (echo -e ".pl 1100i"; cat /usr/man/man1
576 p3 S 0:00 sh -c (cd /usr/man ; (echo -e ".pl 1100i"; cat /usr/man/man1
581 p3 S 0:00 /usr/bin/less -is
585 2 S 0:00 -bash
609 2 S 0:00 man perlrun
610 2 S 0:00 sh -c (cd /usr/man ; (echo -e ".pl 1100i"; cat /usr/man/man1
611 2 S 0:00 sh -c (cd /usr/man ; (echo -e ".pl 1100i"; cat /usr/man/man1
614 2 S 0:00 /usr/bin/groff -Tlatin1 -mandoc
615 2 S 0:00 /usr/bin/less -is
618 2 S 0:00 grotty
719 p0 S 0:00 bash
730 1 S 0:04 /usr/lib/netscape/netscape-communicator /usr/doc/HTML/index.
740 1 S 0:00 (netscape-commun)
749 p0 R 0:00 ps

Ex1: o comando ps dentro do Perl:



$lixo = qx/ps/;


Para quebrar $lixo em linhas basta fazer:


@lixo = split(/\n/,$lixo);


Para tratar cada uma das linhas basta fazer:



foreach $i (@lixo) {
 

}



e assim por diante.
 

2.4. Outras características.

3. O ambiente de programação para o Perl

Sugestão:
emacs - Para o debugger: O Perl já vem com o debugger.
 

4. O uso mais conhecido do Perl: contrução de CGI-scripts

Em geral, ao preencher um formulário na internet, um programa de computador do lado do servidor monta uma página como resposta a este formulário e o envia ao cliente. Este programa do lado do servidor que recebe as informações do cliente, processa-as e monta a página de retorno é um CGI-script. Um CGI-script pode ser escrito em qualquer linguagem, mas o Perl é a linguagem preferida porque pode facilmente extrair os dados do formulário preenchido e gerar uma página de retorno através da manipulação de strings. Por exemplo, o usuário preenche as palavras chave em um sistema de busca e clica o botão submit. O script CGI deve retirar

Que características tornam o Perl interessante para a escrita de CGI-scrits?
As mais conhecidas:

Exemplo de um script:


#!/usr/bin/perl -w
use CGI qw(:standard);

my $nome = param("nome");
print header() . start_html("Exemplo de um CGI") . h1("Exemplo de CGI") ;
if ($nome) {

print p("boa tarde $nome");
} else {
print hr() . start_form();
print p("digite seu nome: " . textfield("nome", ""));
print end_form() . hr();
}

Veja a entrada e saída do ponto de vista do usuário. Obs: Aqui tenho apenas os HTML de entrada e saida porque nao tenho acesso ao diretorio /home/httpd/cgi-bin desta maquina. Ou seja, voce nao estah vendo o formulario sendo processado.
 

5. Como aprender e usar o Perl?

6. Conclusão.

Nesta palestra, você deve ter aprendido: