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

Hello,
I have a string that can have 0 to 30 characters and needs to be converted to only 6 characters. So I currently have something like this:
my @lines = ( "??????????????", "123" ); my $conv; for my $line ( @lines ){ if length( $line > 6 ){ $conv = substr( $line, 0, 6 ); } else { $conv = sprintf( "%6s", substr( $line, 0 ) ); } # do something with $conv; }
This seems to be a bit too complicated to me. Any suggestions to improve this?

Cheers,
PerlingTheUK

Replies are listed 'Best First'.
Re: Alternative to substr on unknown length of scalar
by ikegami (Patriarch) on Oct 19, 2004 at 07:23 UTC
    Simply use
    substr($line.(' 'x6), 0, 6)
    or
    substr("$line      ", 0, 6)
      Great Idea,
      should have come up with it myself really.

      Thanks,
      PerlingTheUK
Re: Alternative to substr on unknown length of scalar
by thospel (Hermit) on Oct 19, 2004 at 09:27 UTC
    sprintf("%.6s", $line)

    update I misunderstood the question. I thought you wanted at most 6 characters, but it seems you want always exactly 6 characters. In that case use:

    sprintf("%6.6s", $line)

      This never works for me. In the event that len($line) > 6, sprintf will print the entire string as follows: (Win32/ActiveState 5.6.1)
      use strict; use warnings; use diagnostics; my $line = 'a'x 8; my $prnline = sprintf("len(line) > 6: [%-6s]\n",$line); $line = 'b' x 6; $prnline .= sprintf("len(line) = 6: [%-6s]\n",$line); $line = 'c' x 3; $prnline .=sprintf("len(line) n 6: [%-6s]\n",$line); print $prnline; __END__ len(line) > 6: [aaaaaaaa] len(line) = 6: [bbbbbb] len(line) n 6: [ccc ]

      I usually go with ikegami's option

      PJ
      use strict; use warnings; use diagnostics;
        It's a . (maximum length) before the 6, not a - (justify left)

        And it should work everywhere, otherwise you found a bug.

      Ouch! how simple.

      Cheers,
      PerlingTheUK
Re: Alternative to substr on unknown length of scalar
by atcroft (Abbot) on Oct 19, 2004 at 07:33 UTC

    Why do you not, in place of the if statement, just do: $conv = sprintf("%6f" substr($line, 0, 6));. In the case of a string longer than 6 characters, it returns only the leftmost 6 characters; in the case of a string shorter than 6 characters, it returns a string padded on the left with spaces.

    Testing:

    $ # String longer than 6 characters $ perl -e '$a="1234567"; $b=sprintf("%6s", substr($a, 0, 6)); print $b +;' 123456 $ # String shorter than 6 characters $ perl -e '$a="123"; $b=sprintf("%6s", substr($a, 0, 6)); print $b;' 123 $ # Example of results from OP's code $ perl -e '$a="1234567"; $b=substr($a, 0, 6); print $b;' 123456 $ perl -e '$a="123"; $b=sprintf("%6s", substr($a, 0)); print $b;' 123

    Hope that helps.

      Because I get annoying warnings (if they are turned on) for setting the length to 6 if a string is shorter than that.

      Cheers,
      PerlingTheUK
Re: Alternative to substr on unknown length of scalar
by BrowserUk (Patriarch) on Oct 19, 2004 at 13:51 UTC
    print pack( 'A6', $_ ) for 'this', 'and that'; this and th

    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "Think for yourself!" - Abigail
    "Memory, processor, disk in that order on the hardware side. Algorithm, algorithm, algorithm on the code side." - tachyon
Re: Alternative to substr on unknown length of scalar
by si_lence (Deacon) on Oct 19, 2004 at 07:37 UTC
    Hi,
    I don't know if this classifies as more elegant than your solution ..
    use strict; use warnings; my @lines = ( "??????????????", "123" ); my $conv; for my $line ( @lines ){ $conv=""; my @c = split('', $line); $conv .= ($c[$_] || 0) for 0..5; print "$conv\n"; }
    si_lence
Re: Alternative to substr on unknown length of scalar
by revdiablo (Prior) on Oct 19, 2004 at 17:15 UTC

    Since these kind of questions always turn into a "let's see how many different alternatives we can come up with" contest, here's my entry:

    for (@lines) { $_ = sprintf "%-6s", /(.{0,6})/; }