http://qs321.pair.com?node_id=723558

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

Dear all, am trying to print only 20 characters in a line from an array. below is my program. I think its logically right.(i may be wrong). How do i fix this?
#!/usr/bin/perl use strict; use warnings; my $str="30 30 36 33 36 36 36 33 36 34 26 24 21 17 17 23 27 27 31 31 3 +4 33 33 33 36 36 37 38 38 38 38 38 35 40 34 34 34 31 37 36 37 37 40 4 +0 49 40 40 40 40 40 40 40 40 33 30 30 30 30 30 42 45 45 45 45 45 49 4 +2 42"; open (OUT,">format.out"); my @array=split(/ /,$str); foreach(@array){ if($_=~/\d+/){ my $flag=0; print OUT "$_ "; my $count++; my $align=20; if ($count/$align==1){print "\n"; $flag=1;} if($flag==1){$count=0;} } }

Replies are listed 'Best First'.
Re: printing 20 characters in a line.
by ikegami (Patriarch) on Nov 14, 2008 at 05:08 UTC
    my $nl = 1; for my $i (0..$#array) { if (!$nl && $i%20==0) { print("\n$array[$i]"); $nl = 1; } else { print(" $array[$i]"); $nl = 0; } } print("\n") if !$nl;
      I got it... how is this one???
      #!/usr/bin/perl my $str="30 30 36 33 36 36 36 33 36 34 26 24 21 17 17 23 27 27 31 31 3 +4 33 33 33 36 36 37 38 38 38 38 38 35 40 34 34 34 31 37 36 37 37 40 4 +0 49 40 40 40 40 40 40 40 40 33 30 30 30 30 30 42 45 45 45 45 45 49 4 +2 42"; @s=split(/ /,$str); for($i=1;$i<=scalar(@s);$i++) { print "$s[$i] "; if($i%20==0) { print "\n"; } } print "\n";
      simple uh.. y didnt i think abt it when i tried first :)
        • You skip the first element.
        • You print an extra element (undef) at the end. use warnings; would have caught that.
        • The use of scalar there is unnecessary.
        • You really should use use strict;.
        • for (my $i=0; $i<@s; $i++)
          is a rather complex way of saying
          for my $i (0..$#s)

        I had a bug in mine too (leading space)

        #!/usr/bin/perl use strict; use warnings; my $str = "30 30 36 33 36 36 36 33 36 34" ." 26 24 21 17 17 23 27 27 31 31" ." 34 33 33 33 36 36 37 38 38 38" ." 38 38 35 40 34 34 34 31 37 36" ." 37 37 40 40 49 40 40 40 40 40" ." 40 40 40 33 30 30 30 30 30 42" ." 45 45 45 45 45 49 42 42"; my @str = split(/ /, $str); my $nl = 1; for my $i (0..$#str) { if ($i == 0 ) { $nl = 0; } elsif ($i % 20 == 0) { $nl = 1; print("\n"); } else { $nl = 0; print(" "); } print($str[$i]); } print("\n") if !$nl;

        Tested.

Re: printing 20 characters in a line.
by cdarke (Prior) on Nov 14, 2008 at 08:52 UTC
    You might consider format for this:
    open (OUT,">format.out"); my @array=grep /\d+/,split(/ /,$str); my $output = "@array"; write OUT; close OUT; format OUT = ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<~~ $output .
Re: printing 20 characters in a line.
by Punitha (Priest) on Nov 14, 2008 at 04:46 UTC

    You can do like this, if the number of character is fixed

    #!/usr/bin/perl use strict; use warnings; my $str="30 30 36 33 36 36 36 33 36 34 26 24 21 17 17 23 27 27 31 31 3 +4 33 33 33 36 36 37 38 38 38 38 38 35 40 34 34 34 31 37 36 37 37 40 4 +0 49 40 40 40 40 40 40 40 40 33 30 30 30 30 30 42 45 45 45 45 45 49 4 +2 42"; open (OUT,">format.out"); my @array=split(/ /,$str); for (0..19){ print OUT "$array[$_] "; } close(OUT);

    Punitha

    Updated after the reply from heidi

    I misunderstood the question, thanks for the reply heidi. So here is the code you needed,

    #!/usr/bin/perl use strict; use warnings; my $str="30 30 36 33 36 36 36 33 36 34 26 24 21 17 17 23 27 27 31 31 3 +4 33 33 33 36 36 37 38 38 38 38 38 35 40 34 34 34 31 37 36 37 37 40 4 +0 49 40 40 40 40 40 40 40 40 33 30 30 30 30 30 42 45 45 45 45 45 49 4 +2 42"; open (OUT,">format.out"); my @array=split(/ /,$str); my $cnt=0; foreach (0..$#array){ ++$cnt; if ($cnt % 20 == 0){ print OUT "$array[$_]\n"; } else{ print OUT "$array[$_] "; } } close(OUT);

    Punitha

      Either you don't need $cnt, or you don't need to iterate over the indexes.
      for (0..$#array){ if ($_ % 20 == 19){ print OUT "$array[$_]\n"; } else{ print OUT "$array[$_] "; } }
      for (@array){ if (++$cnt % 20 == 0){ print OUT "$_\n"; } else{ print OUT "$_ "; } }

      It's probably worth noting the last line has a trailing space and isn't terminated.

      ooopzz, you got me wrong. The whole string has to be printed line by line. Not only the first line. sorry for not giving the expected output format. here it is
      30 30 36 33 36 36 36 33 36 34 26 24 21 17 17 23 27 27 31 31 34 33 33 33 36 36 37 38 38 38 38 38 35 40 34 34 34 31 37 36 37 37 40 40 49 40 40 40 40 40 40 40 40 33 30 30 30 30 30 42 45 45 45 45 45 49 42 42
Re: printing 20 characters in a line.
by luckypower (Beadle) on Nov 14, 2008 at 05:21 UTC
    hellow ....

    your code needs some modifications ..

    in your code if ($count/$align==1){print "\n"; $flag=1;}
    it will print new line on terminal not in file.so change it with print OUT "\n";

    if($flag==1){$count=0;}

    after this line the value of $flag variable is always 1 so change it .....

    One more thing define $flag & $count outside the for loop.

    no need of $align. you can direct compare the $count == 20 .
Re: printing 20 characters in a line.
by ChOas (Curate) on Nov 14, 2008 at 08:48 UTC
    If you don't mind losing $str:

    $str=~s/((?:\d+ ){20})/$1\n/g; print OUT "$str\n";


    GreetZ!,
      ChOas

    print "profeth still\n" if /bird|devil/;

      or, to avoid modifying $str and be rid of trailing spaces

      my $tmp = $str; $tmp =~ s/((?:\s*\d+){20})/$1\n/g; print OUT "$tmp\n";

      update: get rid of leading spaces

      my $tmp = $str; $tmp =~ s/\s*((?:\s*\d+){20})/$1\n/g; print OUT "$tmp\n";
Re: printing 20 characters in a line.
by brsaravan (Scribe) on Nov 14, 2008 at 09:08 UTC
    You can try this
    my @array=split(/ /,$str); my $cnt = 0; map {print "$_ ";($cnt % 20 == 19)? eval{++$cnt;print "\n";}:++$cnt;}@ +array;
Re: printing 20 characters in a line.
by ig (Vicar) on Nov 14, 2008 at 09:43 UTC

    Yet another option using regular expression:

    while ($str =~ /((\s*\d+){1,20})/g) { print OUT "$1\n"; }

    update: get rid of leading spaces

    while ($str =~ /\s*((\s*\d+){1,20})/g) { print "$1\n"; }

    update2: which you can do as a one-liner

    print "$1\n" while ($str =~ /\s*((\s*\d+){1,20})/g);

      To my eye the regex reads better if you start the memory group with a set of digits (thus removing the worry about leading spaces) and then follow with grouped spaces and digits with a quantifier of 0 to 19. That avoids the adjacent \s* tokens which might be a little confusing at first glance. Also, you don't need the parentheses around the match.

      print qq{$1\n} while $str =~ m{(\d+(?:\s+\d+){0,19})}g;

      I hope this is of interest.

      Cheers,

      JohnGG

thats what splice() is for...
by LanX (Saint) on Nov 14, 2008 at 10:30 UTC
    Hi dee! ; )

    maybe using splice() makes it shorter and more maintainable:

    use strict; use warnings; my $str="30 30 36 33 36 36 36 33 36 34 26 24 21 17 17 23 27 27 31 31 3 +4 33 33 33 36 36 37 38 38 38 38 38 35 40 34 34 34 31 37 36 37 37 40 4 +0 49 40 40 40 40 40 40 40 40 33 30 30 30 30 30 42 45 45 45 45 45 49 4 +2 42"; $str=~s/\s*\+//gs; # get rid of linebreaks and these useless pluses my @array=split(/\s+/,$str); # (*) while ( my @chunk = splice(@array,0,20) ) { print "@chunk\n"; }
    tested.

    cheers
    Rolf

    UPDATES:
    (*) splitting /\s+/ makes it more stable than just / /

    ---
    Which song? ;)
      ...these useless pluses
      are put there by the monastery plumbers (which is why they are red). If you download the code using the download link you can avoid them (and the string is all on one line).
        >(which is why they are red)
        Well I'm daltonian, now that you told me I realise it's red! : )

        I'm not sure if there is no better method which would preserve perlsyntax after cut&paste, maybe backslashes at the end of an wraped line!

        hmmm...well this discussion can't be new I'll supersearch for it!

        ---
        Which song? ;)
      Here an alternative version:

      same idea, but without splice() by using more perlish features like list-flattening and arrayslicing

      my @chunk; while ( ( @chunk[0..19] , @array ) = @array ) { print "@chunk\n"; }
      but I think splice is better maintainable!

      UPDATE: Indeed, real splices are better, see "Good" style for splicing arrays for details.

      ---
      Which song? ;)
(DUP) Re: printing 20 characters in a line.
by ikegami (Patriarch) on Nov 14, 2008 at 05:07 UTC

    Duplicate post. Ignore.

    my $nl = 1; for my $i (0..$#array) { if (!$nl && $i%20==0) { print("\n$array[$i]"); $nl = 1; } else { print(" $array[$i]"); $nl = 0; } } print("\n") if !$nl;