qdog
qdog

Reputation: 269

How can I add a newline after X number of characters in Perl?

I was wondering how can I add a newline character (i.e. /n or <br>) after X number of characters.

For example, let's say I have a perl variable $message ="aaaaabbbbbcccccdd". I want to add a newline character after every 5 characters to this variable. So when I print the variable in html it will display:

aaaaa 
bbbbb 
ccccc 
dd    

What is the best way to do this? I was told to use substr or a count function, but I'm not sure how to go about it. Any help will be greatly appreciated. Thanks!

Upvotes: 6

Views: 12812

Answers (9)

nohat
nohat

Reputation: 7281

The unpack method is probably the most efficient, if a bit obtuse. The regex method is probably the most Perlish way to do it. But since this is Perl, there is more than one way to do it, so here are a few other fun ways you could do this:

using List::MoreUtils::natatime ("n-at-a-time"). This method is of course wildly wasteful of memory, creating a scalar for every character in the string.

use List::MoreUtils qw(natatime);

my $in = "aaaaabbbbbcccccdd";
my $out = '';

my $it = natatime 5, split //, $in;
while(my @chars = $it->()) {
    $out .= $_ for @chars;
    $out .= "\n";
}

using the "replacement" argument of substr to splice in newlines, working from the end: (you have to work from the end because otherwise further offsets no longer line up after you start adding newlines; also working from the end means you only calculate length $in at loop start time without using an extra variable)

for(my $i = length($in) - length($in) % 5; $i; $i -= 5) {
    substr($in, $i, 0, "\n");
}

if you want to keep the input variable as is, you could pre-calculate all the offsets and extract them using substr

foreach (map $_ * 5, 0 .. int(length($in) / 5)) {
    $out .= substr($in, $_, 5) . "\n";
}

probably the most succinct way using substr is to use replacement and concatenate the return value:

$out .= substr($in, 0, 5, '') . "\n" while $in;

Upvotes: 0

Robert P
Robert P

Reputation: 15968

Building on Massa's answer, I'd do it like this:

$message = join("\n", unpack('(A5)*', $message ))

running it,

$ perl
use strict;
use warnings;

my $message = "aaaaabbbbbcccccdd";

$message = join("\n", unpack("(A5)*", $message));
print $message;
^D
aaaaa
bbbbb
ccccc
dd

Replace "\n" with whatever you want to actually terminate each line with (eg, "\<br>\n" .)

Upvotes: 4

mpeters
mpeters

Reputation: 4778

Since it appears you're trying to wrap text, I'd look at something like Text::Wrap

Upvotes: 0

Albert Peschar
Albert Peschar

Reputation:

An even shorter option.

$m = "aaaaabbbbbcccccdd";
$m =~ s/(.{1,5})/$1\n/gs;
print $m;

Outputs:

aaaaa
bbbbb
ccccc
dd

Of course I think my version is the best of all presented up to now. ;)

Upvotes: 9

Massa
Massa

Reputation: 8972

I heard that the most efficient way is to use unpack:

say for unpack "(A5)*", "012345678901234567890123456879"

Output:

01234
56789
01234
56789
01234
56879

Upvotes: 4

catwalk
catwalk

Reputation: 6476

echo 123456789abcd|perl -ne'print "$1\n" while s/(^.{5})//;print;'

Upvotes: -2

user80168
user80168

Reputation:

Just pass your string through this regexp:

=~ s/([^\n]{5})/$1\n/g

and you should be fine.

If what you really have is not a random string of random characters, but a text - you might want to use Text::Wrap module instead.

Upvotes: -1

Andre Miller
Andre Miller

Reputation: 15493

In perl, there are many ways to accomplish the same thing ;-)

One them might be:

$message = "aaaaabbbbbcccccdd";
$splitmessage = join ("\n",  ( $message =~ /.{1,5}/gs ));
print $splitmessage, "\n";

Output:

aaaaa
bbbbb
ccccc
dd

Upvotes: 3

Satanicpuppy
Satanicpuppy

Reputation: 1587

substr($string, 0, 5);

Couple that with some variables:

$x = 0;
$newstring = '';
while(length($string)<$x){
    $newstring = $newstring + substr($string, $x, ($x+5)) + '\n';
    $x = $x + 5;
}

Upvotes: -1

Related Questions