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

Hope you guys/gals can help me out with this one.

I am building an address string from disparate elements, i.e.

my $address = $strnum . $strname . $strtype . " " . $strdir;

I then use a regex to remove duplicate whitespace leaving only a single space between the values, i.e. "123 Main St NE".

$address =~ s/  +/ /g;

But I need the $address string to be the same length among all the records, 37 bytes. Tacking on blank space to the end is an acceptable solution for my purposes, but I am unsure how to go about it as the number of spaces needed will vary from address to address. Is there a regex that will force a length while removing duplicate white space from within the string?

Thank in advance for any assistance you can provide. I feel like this should be a simple thing to do, but as Perl novice I am lost.

Replies are listed 'Best First'.
Re: Remove whitespace in string and maintain overall length
by toolic (Bishop) on Nov 19, 2015 at 18:13 UTC
    sprintf can append space to the end of a string:
    use warnings; use strict; my $len = 30; my $address = '123 Main St NE'; $address =~ s/ +/ /g; $address = sprintf "%-${len}s", $address; print ">>>$address<<<\n"; __END__ >>>123 Main St NE <<<
      Wow. That worked the treat, thanks!

      I am no programmer, but rather pull bits and pieces from the code we have floating around. I've see sprintf, but never knew what it was. Looks like I have another Perl toy to play with.

      Thanks again.
Re: Remove whitespace in string and maintain overall length
by BrowserUk (Patriarch) on Nov 19, 2015 at 19:28 UTC

    Use tr to squelch the spaces; and the return value plus a little math to pad to the required length:

    $s = 'fred bill john';; $s .= ' 'x ( 37 - length( $s ) + $s =~ tr[ ][]s ); print "'$s'";; 'fred bill john '

    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority". I knew I was on the right track :)
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Remove whitespace in string and maintain overall length
by kennethk (Abbot) on Nov 19, 2015 at 19:12 UTC
    toolic's solution is pretty good, though for padding I usually prefer making that padding obvious:
    my $address = "$strnum $strname $strtype $strdir"; $address =~ s/\s+/ /g; $address .= ' ' while length $address < 37;
    Note that I've also made the code agnostic as to the kind of whitespace.

    That approach has a lot more operations, but reads easily. Another question to consider is are address guaranteed to be less than 38 characters, and if not should you truncate. So you might do that one as

    my $address = sprintf '%-37.37s', "$strnum $strname $strtype $strdir" +=~ s/\s+/ /rg;
    where I've truncated to 37, used sprintf and the r modifier, and put it on one line to make it as inobvious as possible.

    #11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.

      Your first solution is more inline with what I thought would need to be done, some kind of length interrogation, and very readable as well.

      I am somewhat lucky in that the data being pulled will have a max length of 37 as that was the max length of the various fields used to build the free form address. The source of those fields won't change anytime soon without a overhaul of our current systems.

      To your point though a check like that can never hurt, thanks for that.

Re: Remove whitespace in string and maintain overall length
by Anonymous Monk on Nov 19, 2015 at 20:19 UTC

    Data records? Use pack.

    my $field = pack "A37", ($foo =~ y/ //sr);

Re: Remove whitespace in string and maintain overall length
by RonW (Parson) on Nov 21, 2015 at 03:59 UTC

    kennethk's solution works, but can be made more efficient:

    my $address = "$strnum $strname $strtype $strdir"; $address =~ s/\s+/ /g; $address .= ' ' x (37 - (length $address));

    The expression, ' ' x $n gives you a string of $n spaces with much less overhead than a while or for loop.

    Disclaimer: Not tested. There may be an off by 1 error in calculating the length of the padding.