I'm developing a Perl script that's supposed to generate an HTML file from numerical values from other file. The idea is to read the file that has these values and then list them in a separate HTML file. The file that contains the numerical values is updated every a certain period of time, and those changes should be seen on the HTML.
Even though these values are correctly read (I've tested it) they are not printed in the HTML. Whats-more, the HTML tags are not even printed. This is the code I've written:
#!/usr/bin/perl
use IO::Handle;
use CGI qw(:standard);
print "Status: 200 OK", "\n";
print "Content-type: text/plain", "\n\n";
for(;;) {
open (my $input_file, "<", "/path/to/input/file/input_file.txt") || die "Unable to open the file: $!";
open (my $html_file, ">", "/path/to/html/file/index.html") || die "Unable to open the HTML file: $!";
print $html_file "<html><head><title>title</title><META HTTP-QUIV='refresh' CONTENT='10'></head><body>";
#lines = <$input_file>;
foreach my $line (#lines) {
print $html_file "<p>$line</p>";
}
print $html_file "</body></html>";
sleep 1;
close $input_file || die;
close $html_file || die;
}
The script only works in the first for iteration. What I mean is that the HTML tags and the numerical values are correctly printed in the output file. Then, from iteration 2 to N, the file remains literally empty. I can not see what I'm missing here. Why does it work in the first iteration but not in the following ones?
Thanks in advance
You need to close the file before the sleep. As it stands, the data is flushed to the file by the close and then immediately overwritten by the next open, and left empty for one second
You also need to write
close $html_file or die $!
as the code you have is equivalent to
close($html_file || die)
so your program will never die as long as $html_file is true
Related
so I have a Folder called DATA, and it includes the following: part1.html, part2.html, part3.html, HTML.htm, plain.html, and jojo.jsp.
Now i use the following commmand to open the DATA folder and extract the files containing .htm
opendir(DIR,'DATA');
my(#dir) = grep /\.htm/, readdir (DIR);
closedir(DIR);
It successfully prints out the name of the files containing the extensions .html . Now i wish to use the html file that are filtered and print the data out into the cygwin terminal. I tried to use the files and stored it to a variable, and use a foreach loop to open the first html file using Filehandler and printing out the data init. The loop will repeat itself and do the same for all the other html files. But i seemed to run into the error! Please help!
my $value = join(#dir);
print "$value\n";
foreach(#dir){
my $movies = my $value;
open (FHD, $movies) || die " could not open $movies\n";
my #movies = <FHD>;
my $value2 = join(', ', #movies);
print "$value2\n";
What's with this line?
my $movies = my $value;
You're making this a lot harder than it needs to be.
Just use glob to read the directory as that will automatically include the path information on your found files.
use strict;
use warnings;
use autodie;
for my $html (glob('DATA/*.htm*')) {
print "File: $html\n";
open my $fh, '<', $html;
print <$fh>;
}
I'm new to LWP, URI, Base64. I'm using LWP to post a json string containing an array from a perl script to another perl script. One of the values in the array is a base64 encoded jpg.
I encode the image
open (IMAGE, "./flower.jpg") or die "$!";
$raw_string = do{ local $/ = undef; <IMAGE>; };
$encoded = encode_base64( $raw_string );
$encoded = uri_escape($encoded);
In the other script I decode the image and save it to a directory. The file is slightly larger after saving it than it was originally (a couple kb larger).
$decoded = decode_base64($item->{'FILE'});
open my $fh, '>', "$path/flower.jpg" or die $!;
binmode $fh;
print $fh $decoded;
close $fh;
Also in the second script I pass the json string back and in the first script essentially print what was returned. Everything seems to be returned/prints as expected. When I try to open the file, I just get a standard OS message stating cannot open file. I tried now with a pdf and a jpg. I know I'm missing something somewhere. Thanks for the help!
I want to create a HTML page that will have a table that will populate itself with info from 2 .txt files that are on a remote Linux Server.
or populate a html page on that remote server with the same info from those 2 .txt files and then access that html page using apache's webserver.
something as basic as possible would be nice but I can understand if it's complicated to do with html
honestly, any help at all would be nice.
I would personally do it in PHP. You can read the file and echo it into a table. You can then use the lines of the file for anything you want. I put comments in explaining each step. All you have to do is change $filepath to point at your text file:
Edited: Edited the code to add constraints mentioned by OG poster in comments. There is probably a more optimized way of performing your task, but this works and should introduce some new concepts to you if you are new to PHP
<?php
$filepath = 'files/the_file.txt';
if (file_exists($filepath)) {
$file = fopen($filepath, 'r');
echo '<table border=1>';
while (!feof($file)) {
$line = fgets($file);
$first_char = $line[0];
if ($first_char != '*' && $first_char != '^' && trim($line) != '') {
if (strstr($line, '|')) {
$split = explode('|', $line);
echo '<tr>';
foreach($split as $line) {
echo '<td>'.$line.'</td>';
}
echo '</tr>';
} else {
echo '<tr><td>'.$line.'</td></tr>';
}
}
}
echo '</table>';
} else {
echo 'the file does not exist';
}
?>
I'll do my best to explain it line by line instead of flooding the scrip with comments:
set your file path
If the file exists, continue on. If not, throw the error located at the bottom of the script
open the file
create the table ('<table>')
while the text file is being read, do a series of things: First, get the line. If the first character of the line is a * or ^, or when the line is trimmed there are no characters, skip it completely. Otherwise, continue on
if the line contains a | character, split (explode) the line at all of the | characters. Use this array of split up content and for each piece of content, echo out a new column in the existing row with the current content. Otherwise, there is not | found and you can just echo the line into a row normally
once you are finished up, end the table ('</table>')
Edit #2: The original solution I posted:
<?php
$filepath = '/var/www/files/the_file.txt';
if (file_exists($filepath)) {
$file = fopen($filepath, 'r');
echo '<table border=1>';
while (!feof($file)) {
$line = fgets($file);
echo '<tr><td>'.$line.'</td></tr>';
}
echo '</table>';
} else {
echo 'the file does not exist';
}
?>
HTML can't do anything, HTML is a presentation format.
PHP, Javascript, BASH could do the job in very different ways :
PHP : the server calls the 2 remote files and output the assembled html file into a webpage, then send it to the client
Javascript : the page itself calls the 2 files and add them in itself.
Bash + CURL : a BASH (or PHP, Python...) script creates a .html file containing the data of the 2 files.
One of these might help you, if you can precreate the HTML rather than doing it dynamically. These scripts take CSV as input and output an HTML table:
http://stromberg.dnsalias.org/svn/to-table/
http://stromberg.dnsalias.org/svn/to-table2/
Hi I have a html called 1.html file like this
<div class="t_l"></div>
<some>
lines
of
codes
</some>
<div class="t_r"></div>
I want to replace the content of that div to another one, which stored in the file called "banner".
banner file is
<other>
lines
of some
codes
</other>
So what I want to get is:
<div class="t_l"></div>
<other>
lines
of some
codes
</other>
<div class="t_r"></div>
What I come up with using perl is something like this:
# Slurp file 1.html into a single string
open(FILE,"1.html") or die "Can't open file: $!";
undef $/;
my $file = <FILE>;
open(BANNER,"banner") or die "Can't open file: $!";
undef $/;
my $banner = <BANNER>;
close BANNER;
# Set strings to find and insert
my $first_line = '<div class="t_l"></div>';
my $second_line = '<div class="t_r"></div>';
$file =~ s/$first_line\n.+?\n$second_line#s/$first_line\n$banner\n$second_line/;
close FILE;
# Write output to output.txt
open(OUTPUT,">1new.html") or die "Can't open file: $!";
print OUTPUT $file;
close OUTPUT;
The above code cannot work. Any suggestions?
You're almost there.
The normal regex behavior of . is to match any character except a newline. .+? in your regex doesn't work for you because there are more newline characters between $first_line and $second_line.
Using the /s modifier tells Perl to let . match newline characters, too.
(You also have an extraneous "#s" in your expression)
So a working substitution is:
$file =~ s/$first_line\n.+?\n$second_line/$first_line\n$banner\n$second_line/s;
Go with
$file =~ s/($first_line\n)[^\n]+(\n$second_line)/$1$banner$2/;
or
$file =~ s/(?<=$first_line\n)[^\n]+(?=\n$second_line)/$banner/;
what i am trying to do is get the contents of a file from another server. Since im not in tune with perl, nor know its mods and functions iv'e gone about it this way:
my $fileContents;
if( $md5Con =~ m/\.php$/g ) {
my $ftp = Net::FTP->new($DB_ftpserver, Debug => 0) or die "Cannot connect to some.host.name: $#";
$ftp->login($DB_ftpuser, $DB_ftppass) or die "Cannot login ", $ftp->message;
$ftp->get("/" . $root . $webpage, "c:/perlscripts/" . md5_hex($md5Con) . "-code.php") or die $ftp->message;
open FILE, ">>c:/perlscripts/" . md5_hex($md5Con) . "-code.php" or die $!;
$fileContents = <FILE>;
close(FILE);
unlink("c:/perlscripts/" . md5_hex($md5Con) . "-code.php");
$ftp->quit;
}
What i thought id do is get the file from the server, put on my local machine, edit the content, upload to where ever an then delete the temp file.
But I cannot seem to figure out how to get the contents of the file;
open FILE, ">>c:/perlscripts/" . md5_hex($md5Con) . "-code.php" or die $!;
$fileContents = <FILE>;
close(FILE);
keep getting error;
Use of uninitialized value $fileContents
Which im guessing means it isn't returning a value.
Any help much appreciated.
>>>>>>>>>> EDIT <<<<<<<<<<
my $fileContents;
if( $md5Con =~ m/\.php$/g ) {
my $ftp = Net::FTP->new($DB_ftpserver, Debug => 0) or die "Cannot connect to some.host.name: $#";
$ftp->login($DB_ftpuser, $DB_ftppass) or die "Cannot login ", $ftp->message;
$ftp->get("/" . $root . $webpage, "c:/perlscripts/" . md5_hex($md5Con) . "-code.php") or die $ftp->message;
my $file = "c:/perlscripts/" . md5_hex($md5Con) . "-code.php";
{
local( $/ ); # undefine the record seperator
open FILE, "<", $file or die "Cannot open:$!\n";
my $fileContents = <FILE>;
#print $fileContents;
my $bodyContents;
my $headContents;
if( $fileContents =~ m/<\s*body[^>]*>.*$/gi ) {
print $0 . $1 . "\n";
$bodyContents = $dbh->quote($1);
}
if( $fileContents =~ m/^.*<\/head>/gi ) {
print $0 . $1 . "\n";
$headContents = $dbh->quote($1);
}
$bodyTable = $dbh->quote($bodyTable);
$headerTable = $dbh->quote($headerTable);
$dbh->do($createBodyTable) or die " error: Couldn't create body table: " . DBI->errstr;
$dbh->do($createHeadTable) or die " error: Couldn't create header table: " . DBI->errstr;
$dbh->do("INSERT INTO $headerTable ( headData, headDataOutput ) VALUES ( $headContents, $headContents )") or die " error: Couldn't connect to database: " . DBI->errstr;
$dbh->do("INSERT INTO $bodyTable ( bodyData, bodyDataOutput ) VALUES ( $bodyContents, $bodyContents )") or die " error: Couldn't connect to database: " . DBI->errstr;
$dbh->do("INSERT INTO page_names (linkFromRoot, linkTrue, page_name, table_name, navigation, location) VALUES ( $linkFromRoot, $linkTrue, $page_name, $table_name, $navigation, $location )") or die " error: Couldn't connect to database: " . DBI->errstr;
unlink("c:/perlscripts/" . md5_hex($md5Con) . "-code.php");
}
$ftp->quit;
}
the above using print WILL print the whole file. BUT, for some reason the two regular expresions are returning false. Any idea why?
if( $fileContents =~ m/<\s*body[^>]*>.*$/gi ) {
print $0 . $1 . "\n";
$bodyContents = $dbh->quote($1);
}
if( $fileContents =~ m/^.*<\/head>/gi ) {
print $0 . $1 . "\n";
$headContents = $dbh->quote($1);
}
This is covered in section 5 of the Perl FAQ included with the standard distribution.
How can I read in an entire file all at once?
You can use the Path::Class::File::slurp module to do it in one step.
use Path::Class;
$all_of_it = file($filename)->slurp; # entire file in scalar
#all_lines = file($filename)->slurp; # one line per element
The customary Perl approach for processing all the lines in a file is to do so one line at a time:
open (INPUT, $file) || die "can't open $file: $!";
while (<INPUT>) {
chomp;
# do something with $_
}
close(INPUT) || die "can't close $file: $!";
This is tremendously more efficient than reading the entire file into memory as an array of lines and then processing it one element at a time, which is often—if not almost always—the wrong approach. Whenever you see someone do this:
#lines = <INPUT>;
you should think long and hard about why you need everything loaded at once. It's just not a scalable solution. You might also find it more fun to use the standard Tie::File module, or the DB_File module's $DB_RECNO bindings, which allow you to tie an array to a file so that accessing an element the array actually accesses the corresponding line in the file.
You can read the entire filehandle contents into a scalar.
{
local(*INPUT, $/);
open (INPUT, $file) || die "can't open $file: $!";
$var = <INPUT>;
}
That temporarily undefs your record separator, and will automatically close the file at block exit. If the file is already open, just use this:
$var = do { local $/; <INPUT> };
For ordinary files you can also use the read function.
read( INPUT, $var, -s INPUT );
The third argument tests the byte size of the data on the INPUT filehandle and reads that many bytes into the buffer $var.
Use Path::Class::File::slurp if you want to read all file contents in one go.
However, more importantly, use an HTML parser to parse HTML.
open FILE, "c:/perlscripts" . md5_hex($md5Con) . "-code.php" or die $!;
while (<FILE>) {
# each line is in $_
}
close(FILE);
will open the file and allow you to process it line-by-line (if that's what you want - otherwise investigate binmode). I think the problem is in your prepending the filename to open with >>. See this tutorial for more info.
I note you're also using regular expressions to parse HTML. Generally I would recommend using a parser to do this (e.g. see HTML::Parser). Regular expressions aren't suited to HTML due to HTML's lack of regularity, and won't work reliably in general cases.
Also, if you are in need of editing the contents of the files take a look at the CPAN module
Tie::File
This module relieves you from the need to creation of a temp file for editing the content
and writing it back to the same file.
EDIT:
What you are looking at is a way to slurp the file. May be you have to undefine
the record separator variable $/
The below code works fine for me:
use strict;
my $file = "test.txt";
{
local( $/ ); # undefine the record seperator
open FILE, "<", $file or die "Cannot open:$!\n";
my $lines =<FILE>;
print $lines;
}
Also see the section "Traditional Slurping" in this article.
BUT, for some reason the two regular expresions are returning false. Any idea why?
. in a regular expression by default matches any character except newline. Presumably you have newlines before the </head> tag and after the <body> tag. To make . match any character including newlines, use the //s flag.
I'm not sure what your print $0 . $1 ... code is about; you aren't capturing anything in your matches to be stored in $1, and $0 isn't a variable used for regular expression captures, it's something very different.
if you want to get the content of the file,
#lines = <FILE>;
Use File::Slurp::Tiny. As convenient as File::Slurp, but without the bugs.