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

Hi Monks!
I need to count the characters from account numbers and if they are less than 14 long I need to include a "X" after the initial letters. My code works but need a second opinion if the code is over kill for such task.
#!/usr/bin/perl use strict; use warnings; my $account_1 = "CALI123456-09"; my $account_2 = "FLOR1234567-01"; my $total_count_1; $total_count_1++ while ($account_1 =~ m/./g); print "Account 1 has $total_count_1 characters\n"; if($total_count_1 < 14) { substr($account_1, 4, 0) = 'X'; print "\n^$account_1^\n"; } print "\n*$account_1*\n"; print "*$account_2*\n";
Thanks for looking!

Replies are listed 'Best First'.
Re: Counting to add space to a string
by choroba (Cardinal) on Sep 22, 2011 at 14:09 UTC

      Also, for applying the extra padding, see Multiplicative Operators; specifically:

      print '-' x 80;        # print row of dashes
      Thats right! What about this?
      #!/usr/bin/perl use strict; use warnings; my $account_1 = "CALI123456-09"; my $account_2 = "FLOR1234567-01"; my $total_count_1 = length($account_1); print "Account 1 has $total_count_1 characters\n"; if($total_count_1 < 23) { substr($account_1, 4, 0) = ' '; print "\n^$account_1^\n"; } print "\n*$account_1*\n"; print "*$account_2*\n";
      Thanks!
        Sorry, 23 should be 14!
Re: Counting to add space to a string
by ww (Archbishop) on Sep 22, 2011 at 15:25 UTC
    Take choroba's length suggestion to heart; it's probably the best way to go...

    But, for purposes of generalizing your modification procedure (which is both overkill and underkill, try this for size:

    #!/usr/bin/perl use strict; use warnings; # 927370 - OP seeks to insert 'X' enough times to pad to len=14 AFTER +the LETTERS use 5.012; # NB: First account in this array needs more than one 'X'tension... my @account = qw/CAL2345-06 CALI123456-09 FLOR1234567-01/; for my $account(@account) { my $total_count = 0; while ($account =~ m/./g) { $total_count++ ; } say "At ln 15, |$account| has $total_count characters"; while ($total_count < 14) { substr($account, 4, 0) = 'X'; $total_count++; } continue { # loop till $total_count == 14 ! say "At ln 21, |$account| has $total_count characters"; } next; }

    Execution and output:

    C:\>927370.pl At ln 15, |CAL2345-06| has 10 characters At ln 21, |CAL2X345-06| has 11 characters <!-- first insert, X in wro +ng position At ln 21, |CAL2XX345-06| has 12 characters At ln 21, |CAL2XXX345-06| has 13 characters At ln 21, |CAL2XXXX345-06| has 14 characters <!-- but we do get to 14, + despite short orig. At ln 15, |CALI123456-09| has 13 characters At ln 21, |CALIX123456-09| has 14 characters <!-- 14 after extension At ln 15, |FLOR1234567-01| has 14 characters <!-- 14 in original array C:\>

    hth

    Extensively updated: pasted similar output and code but with mismatching ln numbers.

      In your first example, your code is inserting the X after the fourth char, but the OP says "after the initial letters".

        Good point; ++. Another arguement for regex and length!>

        I failed to consider that OP's substr($account_1, 4, 0) hard codes the insert point; in fact, offhand, I don't see a direct way (other than a regex to find the last, initial letter (.oO ... there might be some non-initial letters? pos, and length) to fix that in my code.

        Update: That is, I didn't see it until your Re: Counting to add space to a string. Elegant and concise: ++ again!

Re: Counting to add space to a string
by johngg (Canon) on Sep 22, 2011 at 18:45 UTC

    You could also use look-behind and look-ahead assertions to find the point in the string where the initial letters end insert the required number of 'X's using a regex substitution using the 'e' modifier.

    knoppix@Microknoppix:~$ perl -E ' > @accts = qw{ > CAL2345-06 > CALI123456-09 > FLOR1234567-01 > MEGA9988776655-43 > }; > say for > map { > s{ (?<=[a-zA-Z]) (?![a-zA-Z]) }{ q{X} x ( 14 - length ) }xe; > $_; > } > @accts;' CALXXXX2345-06 CALIX123456-09 FLOR1234567-01 MEGA9988776655-43 knoppix@Microknoppix:~$

    I hope this is helpful.

    Cheers,

    JohnGG

      Or do a normal greedy match on the letters, and insert the X's after them in the same fashion:

      s{ ^([a-zA-Z]+) }{ $1 . 'X' x ( 14 - length ) }xe;
Re: Counting to add space to a string
by thundergnat (Deacon) on Sep 22, 2011 at 15:13 UTC
    chomp, m/([^A-Z])/, print $`, 'X' x (14 - length), $+, $', "\n" while +<DATA>; __DATA__ CALI123456-09 FLOR1234567-01
Re: Counting to add space to a string
by Util (Priest) on Sep 22, 2011 at 15:54 UTC
    for my $acct ( qw( CAL2345-06 CALI123456-09 FLOR1234567-01 ) ) { my $formatted_account_id = format_account_id($acct); print "'$formatted_account_id'\n"; } sub format_account_id { my ($acct) = @_; my $padding_needed = 14 - length($acct); return $acct if $padding_needed < 1; $acct =~ m{ \A ([[:alpha:]]+) (.+) \z }msx or warn "Bad format: '$acct'" and return $acct; return $1 . ( 'X' x $padding_needed ) . $2; }
    Output:
    'CALXXXX2345-06' 'CALIX123456-09' 'FLOR1234567-01'
Re: Counting to add space to a string
by pvaldes (Chaplain) on Sep 22, 2011 at 22:55 UTC

    another way probably

    if (/^[[:allnum:]]{1,13}$/){ =~ s/^([[:allnum:]]{1,13})$/$1.'X'/ }

    to be used inside a loop

    I need to include a "X" after the initial letters.

    You could print the X in any position you want. i.e, after the first letter

    if (/^[[:allnum:]]{1,13}$/){ =~ s/^([[:allnum:]]{1})([[:allnum:]]{1,12})$/$s1 .'X'. $2/ }