r2 - 11 May 2009 - JoenioCosta
Script Perl para ler arquivo PHP
Dúvida de Pedro César na lista Cascavel-PM em 8 de abril de 2009 fonte: http://mail.pm.org/pipermail/cascavel-pm/2009-April/014742.html Atenção: o texto abaixo não é uma cópia fiel das mensagens no link acima, em algumas ocasiões o texto foi adaptado para melhor entendimento do leitor.Pergunta
Pessoal, to iniciando em Perl e to tentando criar um script que leia um arquivo PHP que tenho no servidor, segue o código:#!/usr/local/bin/perl use strict; $file = 'http://www.site.com/classes/arquivo.php'; open(INFILE, $file); @lines = <INFILE>; #close(INFILE); print(@lines);Porém o código não exibe o conteúdo do arquivo PHP, gostaria de contar com a ajuda dos mais experientes.
Resposta
Resposta de Otávio Fernandes
Estou vendo, realmente, que você está começando comPerl. Bom, primeira coisa, você está passando uma URI para acessar o arquivo... acredito que você está rodando o script no mesmo servidor onde este arquivo se encontra, então, você tem que passar path para acessar diretamente, exemplo:
my $file = q{/var/tmp/arquivo.php};
O script ficaria assim (com algumas melhorias):
#!/usr/bin/env perl
use strict;
use warnings;
my $file = q{/var/tmp/arquivo.php};
open( my $FH, q{<}, $file ) or die $!;
while( <$FH> ) {
print;
}
close( $FH );
Caso você queria acessar este arquivo remoto, via protocolo HTTP, você pode usar o módulo LWP (por exemplo).
Resposta de breno
Recomendo vivamente que você siga a recomendação do Daniel e aprenda um pouco mais sobre o básico da linguagem com a excelente documentação doPerl em http://perldoc.perl.org em inglês e http://perldoc.perl.org.br em português.
Como você deve ter percebido pela resposta do Otávio em Perl existe sempre mais de uma maneira de se fazer as coisas! A grande questão é que, enquanto uma ou outra forma são simples diferenças de "sotaque", outras são realmente mais recomendadas, por diversos motivos.
A primeira coisa que você deveria se acostumar a fazer é formular perguntas que nos ajudem a te ajudar. Por exemplo, você disse:
"to tentando criar um script que leia um arquivo PHP que tenho no servidor"
E isso levou o Otávio a crer que o arquivo era local, e não remoto. Depois, você disse:
"Porém o código não exibe o conteúdo do arquivo ==PHP=="
Nesse ponto o melhor a fazer é dizer algo como: "estava esperando X e aconteceu Y". Dizer "não funcionou" não nos diz muita coisa =)
Por exemplo, se você ativa o pragma strict ( use strict ), então todas as suas variáveis precisam ser pré-declaradas! Como? Colocando my na frente delas antes de usá-las pela primeira vez (e lá se foi uma das suas dúvidas, espero!
)
Aí seguem duas dicas importantes:
- 1) Seus programas devem sempre começar com:
use strict; use warnings;Exatamente como o Otávio respondeu. (alguns desenvolvedores gostam de tirar o "warnings" quando o sistema entra em produção, mas não faça isso:-) )
- 2) Pra você que está começando, o
Perloferece um outro pragma muito interessante, e recomendo que use:
use diagnostics;Coloque esse pragma logo abaixo do
use warnings, e o Perl te dará dicas sobre o que ele acha que está acontecendo e como solucionar o problema. Por exemplo, rodando o seu programa com esses três pragmas ativos, obtemos a saída:
Global symbol "$file" requires explicit package name at pedro.pl line 6.
Global symbol "$file" requires explicit package name at pedro.pl line 7.
Global symbol "@lines" requires explicit package name pedro ex.pl line 8.
Global symbol "@lines" requires explicit package name at pedro.pl line 11.
Execution of pedro.pl aborted due to compilation errors (#1)
(F) You've said "use strict" or "use strict vars", which indicates
that all variables must either be lexically scoped (using "my" or "state"),
declared beforehand using "our", or explicitly qualified to say
which package the global variable is in (using "::").
Uncaught exception from user code:
Global symbol "$file" requires explicit package name at pedro.pl line 6.
Global symbol "$file" requires explicit package name at pedro.pl line 7.
Global symbol "@lines" requires explicit package name at pedro.pl line 8.
Global symbol "@lines" requires explicit package name at pedro.pl line 11.
Execution of pedro.pl aborted due to compilation errors.
at ex.pl line 11
Viu a dica ali no meio? Pois é
Outra coisa que você reparou foi que o Otávio usou o comando open com 3 argumentos, em vez de dois. Essa é a forma recomendada de usar o open, pois nela você diz explicitamente qual o modo de abertura (leitura, escrita, etc), e evita código potencialmente inseguro. Isso porque, usando o open com dois argumentos apenas, você não consegue forçar o modo desejado. Afinal, o open aceita nessa forma que você especifique o modo dentro da variável, como $file = '>meu_arquivo.txt'. Se alguém conseguir editar o conteúdo da variável, pode causar muitos problemas!
Mas ele fez mais do que isso... se você reparar, ele usou como handle de arquivo uma variável, e não uma palavra em maiúsculas ( bareword ). Esse é o procedimento recomendado também, especialmente porque barewords são globais do pacote (em vez de léxicas, como as variáveis declaradas com my ) e podem causar muitos problemas inesperados (especialmente se você acidentalmente usar a mesma bareword para abrir diferentes arquivos).
Para mais informações, consulte:
$ perldoc -f openOutra coisa que ele fez foi usar operadores quote-like em vez dos quotes em si. Em
Perl, você pode especificar um bloco entre aspas simples como q{} ou entre aspas duplas como qq{}. Isso é particularmente útil para evitar precisar escapar caracteres especiais. Por exemplo, suponha que você queira armazenar em $var o conteúdo:
%_@'''0283',z''''''..'.'Você teria que fazer algo como:
my $var = '%_@\'\'\'0283\',z\'\'\'\'\'\'..\'.\'';O que é no mínimo confuso. Que tal assim?
my $var = q{%_@'''0283',z''''''..'.'};
Bem mais fácil, não? O perl faz o que você quer e não deixa os pliques internos interferirem no seu comando
Usar q{} e qq{} é especialmente útil ao fazer one-liners, evitando que os quotes sejam interpolados pela shell. Dentro do código, a menos que você tenha um bom motivo como o acima, é só uma questão de preferência mesmo. Então fazer '>' ou q{>} não importa. Existe um outro operador, o qw(), que separa elementos de listas, de modo que em vez de você escrever assim:
my @herculoids = ( 'igoo', 'tundro', 'zok', 'gloop', 'gleep' );Pode escrever assim:
my @herculoids = qw( igoo tundro zok gloop gleep );Que costuma ser muito mais fácil de escrever, e de ler. Outra coisa que ele fez diferente foi ler o arquivo uma linha por vez, que é mais eficiente do que ler tudo de uma vez pra dentro de um array, e é o procedimento recomendado, especialmente para arquivos grandes. Ele usou a variável de contexto
$_, mas vamos deixar isso pra depois que você tiver se acostumado com o Perl
Finalmente, como nota pessoal, em Perl a maioria dos parêntesis são opcionais e devem ser usados apenas para evitar ambiguidade. Assim, em vez de fazer:
open (my $FH, '<', $filename) or die $!; ... print ($linha); ... close($FH);Você pode fazer:
open my $FH, '<', $filename or die $!; ... print $linha; ... close $FH;No caso do
open, muita gente (inclusive eu) gosta de colocar o or na linha de baixo, com uma leve identação. Assim:
open my $FH, '<', $filename
or die "erro abrindo arquivo: $!\n";
Ou você pode usar o pragma autodie, mas isso também é outra história
Enfim, já me alonguei muito. A moral da história é:
Experimente as coisas do jeito que o Otávio disse.
Leia a documentação indicada pelo Daniel em http://www.perl.org.br/Perldoc/V500807/Perlintro

