Modifying a HP/GL2 output file using Perl

S

Steve Hemond

Hi gurus,

I read some docs about Perl and I think it would be the best language to
suit my acutal need.

I have to change plotter pen widths from an HP/GL2 output file with specific
widths. An HP/GL2 is a plain-text file filled with plotter commands. The
one I need to check are :
PSx (where x = pen number) = PEN SELECT
PWx (where x = width) = PEN WIDTH

In that kind of file, you will see PS1 followed by a bunch of coordinates
and stuff. From there you can see that every command after the PS1 is for
the PEN NUMBER ONE. I have to check where the PW is, and affect a new width
right after it. I have to do this to all pens. I already know which width
goes for each pen. My problem is that the number of caracters between each
PSx and PWx are different from time to time.

Unless anyone has a better idea it would probably need to read the file byte
per byte, and when a PSx is read, the program will remember the current
pen, and when reaching the next PWx, it will affect the corresponding width
for the current pen.

Is there an quick and effective way to do such kind of things with Perl?
From what I've read, I can make a Perl script read a file LINE by LINE but
I don't know about reading byte per byte.

Any ideas?

Thanks in advance,

Steve
 
B

Bob Walton

Steve said:
Hi gurus,

I read some docs about Perl and I think it would be the best language to
suit my acutal need.

I have to change plotter pen widths from an HP/GL2 output file with specific
widths. An HP/GL2 is a plain-text file filled with plotter commands. The
one I need to check are :
PSx (where x = pen number) = PEN SELECT
PWx (where x = width) = PEN WIDTH

In that kind of file, you will see PS1 followed by a bunch of coordinates
and stuff. From there you can see that every command after the PS1 is for
the PEN NUMBER ONE. I have to check where the PW is, and affect a new width
right after it. I have to do this to all pens. I already know which width
goes for each pen. My problem is that the number of caracters between each
PSx and PWx are different from time to time.

Unless anyone has a better idea it would probably need to read the file byte
per byte, and when a PSx is read, the program will remember the current
pen, and when reaching the next PWx, it will affect the corresponding width
for the current pen.

Is there an quick and effective way to do such kind of things with Perl?
From what I've read, I can make a Perl script read a file LINE by LINE but
I don't know about reading byte per byte.

Any ideas?


Unless your files are huge (>10 Mb), you should probably slurp them into
a string, operate on the string with a well-crafted substitution, and
write it out again. Perhaps something like:

use strict;
use warnings;
my $in;
my %width=(1=>3,2=>8,3=>5); # pen number => width
{local $/;$in=<DATA>;}
$in=~s/PS(\d+)(.*?)PW(\d+)/"PS$1$2PW".$width{$1}/egs;
print $in;
__END__
xxxPS1blahblahPW13blahblahPS2blahPW1blahPS3blahPW2etcetc
and some more PS1 blah PW123 blah blah blah

That outputs:

D:\junk>perl junk363.pl
xxxPS1blahblahPW3blahblahPS2blahPW8blahPS3blahPW5etcetc
and some more PS1 blah PW3 blah blah blah

D:\junk

The above requires that there be no whitespace between the PS and the
digit follow, and the same for the PW field. It also assumes there will
be only one PW field following a given PS field (if there could be more
than one, something slightly fancier would be needed). Note that if you
neglect to assign a given pen a width value, the corresponding PW field
will not have a digit.


....
 
A

Anno Siegel

Steve Hemond said:
Hi gurus,

I read some docs about Perl and I think it would be the best language to
suit my acutal need.

I have to change plotter pen widths from an HP/GL2 output file with specific
widths. An HP/GL2 is a plain-text file filled with plotter commands. The
one I need to check are :
PSx (where x = pen number) = PEN SELECT
PWx (where x = width) = PEN WIDTH

In that kind of file, you will see PS1 followed by a bunch of coordinates
and stuff. From there you can see that every command after the PS1 is for
the PEN NUMBER ONE. I have to check where the PW is, and affect a new width
right after it. I have to do this to all pens. I already know which width
goes for each pen. My problem is that the number of caracters between each
PSx and PWx are different from time to time.

Unless anyone has a better idea it would probably need to read the file byte
per byte, and when a PSx is read, the program will remember the current
pen, and when reaching the next PWx, it will affect the corresponding width
for the current pen.

Is there an quick and effective way to do such kind of things with Perl?
From what I've read, I can make a Perl script read a file LINE by LINE but
I don't know about reading byte per byte.

Bob Walton has suggested slurping the file, and that looks indeed
attractive because the content of one line can influence what happens
many lines later.

However, the problem can be dealt with line-wise too.

If you work through the file and pick up a new line, split the
line into parts where a "PSx" is found. Then in each part all
"PWx" must be changed in a uniform way. The width for the first
part will be the one that has been used for the last part of the
last line. The width of the other parts is determined by the "PSx"
statement they begin with. You will have to keep the last width
used for the next line you pick up. So a function to deal with a
line would take a line to change and the initial width for arguments,
and return the changed line and the new width:

sub deal_with_line {
my ( $line, $width) = @_;
my @parts = split /(?=PS\d+)/, $line; # note zero width pattern
for ( @parts ) {
$width = $width{ $1} if /^PS(\d+)/;
next unless defined $width; # may happen before the first "PSx"
s/PW\d+/PW$width/g;
}
( join( '', @parts), $width);
}

The main program becomes:

my $width;
while ( <DATA> ) {
( $_, $width) = deal_with_line( $_, $width);
print;
}

Anno
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,143
Latest member
SterlingLa
Top