Modifying a HP/GL2 output file using Perl

Discussion in 'Perl Misc' started by Steve Hemond, Sep 14, 2003.

  1. Steve Hemond

    Steve Hemond Guest

    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
     
    Steve Hemond, Sep 14, 2003
    #1
    1. Advertising

  2. Steve Hemond

    Bob Walton Guest

    Steve Hemond wrote:

    > 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.


    ....


    > Steve


    --
    Bob Walton
     
    Bob Walton, Sep 14, 2003
    #2
    1. Advertising

  3. Steve Hemond

    Anno Siegel Guest

    Steve Hemond <> wrote in comp.lang.perl.misc:
    > 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
     
    Anno Siegel, Sep 15, 2003
    #3
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Shawn Zabel

    Perl & XS -- Modifying a char*

    Shawn Zabel, Jul 19, 2004, in forum: Perl
    Replies:
    0
    Views:
    538
    Shawn Zabel
    Jul 19, 2004
  2. AspDotNetDeveloper

    Modifying output in Repeater

    AspDotNetDeveloper, Jul 17, 2003, in forum: ASP .Net
    Replies:
    2
    Views:
    370
    AspDotNetDeveloper
    Jul 17, 2003
  3. Replies:
    2
    Views:
    355
  4. Replies:
    24
    Views:
    1,112
    santosh
    Jul 18, 2007
  5. Joe Hudson
    Replies:
    3
    Views:
    459
    Arne Vajhøj
    May 24, 2008
Loading...

Share This Page