gcmandrake has asked for the wisdom of the Perl Monks concerning the following question:

Greetings and Salutations Perl Monks,

My objective is to wrap a SPICE statement string that is greater than 79 characters onto multiple lines. The lines following the first line must be preceeded with a continuation character, a plus (+) sign. For readability purposes the line should be broken on word boundries (whitespace).

I previously found an answer to my question on this site two years ago (for a slightly different problem). I found when I needed to expand this solution to pre-fix the continued lines with a "+"-sign it failed. I'm not sure why it is failing. Here is a snippet of the code. The original code was contributed by Anonymous Monk & Poznick.

$spice_str = "VIN IN VSS PWL ( 0ns 0.0 4ns 2.4 25ns 0.0 50ns 2.4 51ns +0.0 75ns 2.4 76ns 0.0 100ns 2.4 101ns 0.0 )"; $rest = $spice_str; @text = (); while ( $rest ne '' ) { $rest =~ /(.{1,25}[^a-zA-Z0-9.])/ms; push @text, $1; $rest = $'; } foreach ( @text ) { print "$_\n"; }
Works, but if I change it slightly:
$rest = "+ " . $';
It appears to hang, like awaiting input. I realize that I could alter the final print foreach statement to fix this issue, but I wanted to understand what's going on. And, of course, I would like to make this as elegant (and readable by my customer) as possible.

An unworthy Physicist posing as a Perl programmer,

gcmandrake

Replies are listed 'Best First'.
Re: Splitting SPICE lines on 'word' boundries closest to a certain length
by kvale (Monsignor) on Mar 18, 2004 at 21:34 UTC
    Hey, I'm a physicist, too. Its OK :)

    Here I create a flag to detect the first line:

    my $spice_str = "VIN IN VSS PWL ( 0ns 0.0 4ns 2.4 25ns 0.0 50ns 2.4 51 +ns 0.0 75ns 2.4 76ns 0.0 100ns 2.4 101ns 0.0 )"; my $rest = $spice_str; my @text; my $first = 1; while ( $rest ne '' ) { $rest =~ /(.{1,25}[^a-zA-Z0-9.])/; push @text, ($first ? $1 : "+$1"); $rest = $'; $first = 0; } foreach ( @text ) { print "$_\n"; }

    -Mark

Re: Splitting SPICE lines on 'word' boundries closest to a certain length
by graff (Chancellor) on Mar 19, 2004 at 02:33 UTC
    Looking at your while loop, you should notice that when $' is an empty string, and you do this:
    $rest = "+ " . $';
    the condition for exiting the while loop -- $rest eq '' -- will never be met. The easiest fix (involving the smallest change to the existing code) would be:
    $rest = ( $' ) ? "+ $'" : '';
    or something equivalent. Personally, though, I tend to prefer (r)index and substr for this sort of problem -- something like this (using index, because you seem to be willing to accept longer strings when looking for a place to break):
    while ( length($rest) > 25 ) { my $break = index( $rest, ' ', 25 ); last if ( $break < 0 ); # no more spaces to break on push @text, substr( $rest, 0, $break ); $rest = '+ ' . substr( $rest, $break ); } push @text, $rest if ( length( $rest ));
      Thanks to all you monks for your elegant (and thought provoking) solutions. My customer was delighted with the code, but now wants more features. And so it goes... Thanks again. gcmandrake
Re: Splitting SPICE lines on 'word' boundries closest to a certain length
by belg4mit (Prior) on Mar 18, 2004 at 21:58 UTC
    Text::Wrap

    --
    I'm not belgian but I play one on TV.