Estou tentando abrir um arquivo .html como uma grande string longa. Isso é o que eu tenho:
open(FILE, 'index.html') or die "Can't read file 'filename' [$!]\n";
$document = <FILE>;
close (FILE);
print $document;
o que resulta em:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN
No entanto, quero que o resultado seja semelhante a:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
Dessa forma, posso pesquisar todo o documento com mais facilidade.
Respostas:
Adicionar:
antes de ler a partir do identificador de arquivo. Consulte Como posso ler um arquivo inteiro de uma vez? , ou
Consulte Variáveis relacionadas a filehandles em
perldoc perlvar
eperldoc -f local
.Aliás, se você puder colocar seu script no servidor, poderá ter todos os módulos que desejar. Consulte Como mantenho meu próprio diretório de módulo / biblioteca? .
Além disso, Path :: Class :: File permite que você slurp e vomite .
Path :: minúsculo dá ainda mais métodos de conveniência, como
slurp
,slurp_raw
,slurp_utf8
bem como os seusspew
homólogos.fonte
$/
, provavelmente deve adicionar links para mais informações.local
e nãomy
.Eu faria assim:
Observe o uso da versão de três argumentos de open. É muito mais seguro do que as versões antigas de dois (ou um) argumentos. Observe também o uso de um identificador de arquivo léxico. Manipuladores de arquivos lexicais são mais agradáveis do que as variantes de palavras de barras antigas, por muitos motivos. Estamos aproveitando um deles aqui: fecham quando saem do escopo.
fonte
Com Arquivo :: Slurp :
Sim, até você pode usar o CPAN .
fonte
Can't locate File/Slurp.pm in @INC (@INC contains: /usr/lib/perl5/5.8/msys
:(Todas as postagens são ligeiramente não idiomáticas. O idioma é:
Geralmente, não há necessidade de definir $ / para
undef
.fonte
local $foo = undef
é apenas o método sugerido de Perl Best Practice (PBP). Se estamos postando trechos de código, acho que fazer o nosso melhor para deixar isso claro seria Uma coisa boa.De perlfaq5: Como posso ler um arquivo inteiro de uma vez? :
Você pode usar o módulo File :: Slurp para fazer isso em uma etapa.
A abordagem usual do Perl para processar todas as linhas em um arquivo é fazer uma linha por vez:
Isso é tremendamente mais eficiente do que ler o arquivo inteiro na memória como uma matriz de linhas e, em seguida, processá-lo um elemento por vez, o que geralmente - senão quase sempre - é a abordagem errada. Sempre que você vir alguém fazer isso:
você deve pensar muito sobre por que precisa de tudo carregado de uma vez. Não é apenas uma solução escalonável. Você também pode achar mais divertido usar o módulo Tie :: File padrão ou as ligações $ DB_RECNO do módulo DB_File, que permitem vincular um array a um arquivo para que, ao acessar um elemento, o array realmente acesse a linha correspondente no arquivo .
Você pode ler todo o conteúdo do filehandle em um escalar.
Isso desfaz temporariamente o separador de registro e fecha automaticamente o arquivo na saída do bloco. Se o arquivo já estiver aberto, basta usar este:
Para arquivos comuns, você também pode usar a função de leitura.
O terceiro argumento testa o tamanho do byte dos dados no filehandle INPUT e lê esse número de bytes no buffer $ var.
fonte
Uma maneira simples é:
Outra forma é alterar o separador de registro de entrada "$ /". Você pode fazer isso localmente em um bloco vazio para evitar alterar o separador de registro global.
fonte
{local $/; open(my $f, '<', 'filename'); $d = <$f>;}
open
ou a chamada implicitamenteclose
.my $d = do{ local $/; open(my $f, '<', 'filename') or die $!; my $tmp = <$f>; close $f or die $!; $tmp}
. (Isso ainda tem o problema de não especificar a codificação de entrada.)use autodie
, a principal melhoria que eu pretendia mostrar foi o lexical filehandle e o 3 arg open. Existe algum motivo para você estardo
fazendo isso? por que não simplesmente despejar o arquivo em uma variável declarada antes do bloco?Defina
$/
comoundef
(veja a resposta de jrockway) ou apenas concatene todas as linhas do arquivo:É recomendado usar escalares para filehandles em qualquer versão Perl que o suporte.
fonte
Outra forma possível:
fonte
Você só está obtendo a primeira linha do operador diamante
<FILE>
porque o está avaliando no contexto escalar:No contexto de lista / matriz, o operador diamante retornará todas as linhas do arquivo.
fonte
<=>
e o<>
é o operador diamante.Eu faria isso da maneira mais simples, para que qualquer pessoa pudesse entender o que acontece, mesmo que existam maneiras mais inteligentes:
fonte
<f>
- retorna um array de linhas de nosso arquivo (se$/
tiver o valor padrão"\n"
) e entãojoin ''
colocará este array em.fonte
Esta é mais uma sugestão de como NÃO fazer isso. Acabei de encontrar um bug em um aplicativo Perl bastante grande. A maioria dos módulos tinha seus próprios arquivos de configuração. Para ler os arquivos de configuração como um todo, encontrei esta única linha do Perl em algum lugar da Internet:
Ele reatribui o separador de linha conforme explicado anteriormente. Mas também reatribui o STDIN.
Isso teve pelo menos um efeito colateral que me custou horas para descobrir: ele não fecha o identificador de arquivo implícito corretamente (uma vez que não chama
close
nada).Por exemplo, fazer isso:
resulta em:
O estranho é que o contador de linha
$.
é aumentado para cada arquivo em um. Não é redefinido e não contém o número de linhas. E não é redefinido para zero ao abrir outro arquivo até que pelo menos uma linha seja lida. No meu caso, eu estava fazendo algo assim:Por causa desse problema, a condição era falsa porque o contador de linha não foi redefinido corretamente. Não sei se isso é um bug ou simplesmente um código errado ... Também chamar
close;
oderclose STDIN;
não ajuda.Substituí esse código ilegível usando open, string concatenation e close. No entanto, a solução postada por Brad Gilbert também funciona, pois usa um identificador de arquivo explícito.
As três linhas no início podem ser substituídas por:
que fecha corretamente o identificador de arquivo.
fonte
Usar
antes
$document = <FILE>;
.$/
é o separador de registro de entrada , que é uma nova linha por padrão. Ao redefini-lo paraundef
, você está dizendo que não há separador de campo. Isso é chamado de modo "slurp".Outras soluções como
undef $/
elocal $/
(mas nãomy $/
) redeclaram $ / e, portanto, produzem o mesmo efeito.fonte
Você pode simplesmente criar uma sub-rotina:
fonte
Não sei se é uma boa prática, mas costumava usar isso:
fonte
Todas essas são boas respostas. MAS se você está com preguiça e o arquivo não é tão grande e a segurança não é um problema (você sabe que não tem um nome de arquivo corrompido), então você pode dizer:
fonte
Você pode usar cat no Linux:
fonte