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

Can somebody help me with a short codesnippet to insert space into a string after, let's say 16 chars?
So "longlonglonglonglonglonglonglonglong" would become "longlonglonglong longlonglonglong long"

Here is what I came up with:
join(' ', split(/\w/,$string,(length($string) ) )
See what I mean (but it doesn't work, yet...)

Replies are listed 'Best First'.
Re: How to split a string into chunks of length n or less
by moritz (Cardinal) on Aug 21, 2008 at 15:52 UTC
    Something like this:
    my $x = 'abc' x 10; $x =~ s/(.{4})/$1 /sg; print $x, "\n"; __END__ abca bcab cabc abca bcab cabc abca bc

    If you only want to insert after word characters, you can use s/(\w{4})/$1 /g instead.

Re: How to split a string into chunks of length n or less
by jethro (Monsignor) on Aug 21, 2008 at 15:54 UTC
    s/(.{16})/$1 /g;
Re: How to split a string into chunks of length n or less
by Skeeve (Parson) on Aug 21, 2008 at 16:12 UTC

    Yesterday I had to learn that string operations might be more efficient. So here we go:

    my $x = "0123456789abcdef" x 4 . "XXX"; my $chunksize= 16; for (my $i=$chunksize*int((length($x)-1)/$chunksize);$i;$i-=$chunksize +) { substr($x,$i,0)=" "; }; print $x;

    And if you really want to use split Or you might still want a regular expression:

    join " ",$x=~/(.{1,$chunksize})/g

    Update to my first codesnippet: Thanks to oshalla's comment above I noticed that I also had a space too much when the string has a length being a multiple of chunksize.


    s$$([},&%#}/&/]+}%&{})*;#$&&s&&$^X.($'^"%]=\&(|?*{%
    +.+=%;.#_}\&"^"-+%*).}%:##%}={~=~:.")&e&&s""`$''`"e
      I wrote a small benchmark, under the assumption that the implementation is not allowed to modify the original string, and if it does it has to take a copy first.

      I found out that all versions are extremely fast, and thus not easy to benchmark. So probably my benchmark is flawed, take it with a grain of salt.

      Here are the results (with perl5.10.0):

      Rate readl subst unpack substr readl 78783885/s -- -17% -18% -24% subst 95302528/s 21% -- -1% -8% unpack 96105165/s 22% 1% -- -8% substr 103929656/s 32% 9% 8% --
      And then I ran it again:
      Rate subst readl substr unpack subst 81695687/s -- -1% -36% -65% readl 82899185/s 1% -- -35% -65% substr 128382089/s 57% 55% -- -46% unpack 235800076/s 189% 184% 84% --
      and thought "WTF?"

      I increased the length of the source string by a factor of 100, and started the benchmark again. It still runs (after about 15 minutes).

      My conclusions are that the differences are so small (or my benchmark so flawed...) that you can basically neglect them.

        You missed the corrections some have added. There is still the extra space at the end in certain cases. See oshalla's post and my update above.

        I added my second code snippet and ran this:

        My results:
        Rate unpack substr subst re readl unpack 29656695/s -- -5% -8% -14% -16% substr 31367657/s 6% -- -3% -9% -11% subst 32410531/s 9% 3% -- -6% -8% re 34622792/s 17% 10% 7% -- -2% readl 35251272/s 19% 12% 9% 2% --

        s$$([},&%#}/&/]+}%&{})*;#$&&s&&$^X.($'^"%]=\&(|?*{%
        +.+=%;.#_}\&"^"-+%*).}%:##%}={~=~:.")&e&&s""`$''`"e
Re: How to split a string into chunks of length n or less
by dreadpiratepeter (Priest) on Aug 21, 2008 at 15:54 UTC
    How about:
    $str =~ s/(.{16})/$1 /g;


    -pete
    "Worry is like a rocking chair. It gives you something to do, but it doesn't get you anywhere."

      Well:

      $str =~ s/(.{16})(?!\Z)/$1 /g ;
      would avoid sticking a space on the end of a string which was originally an exact multiple of 16 characters.
      $str =~ s/(\w{16}(?=\w)/$1 /g ;
      would split any "words" longer than 16 characters.

Re: How to split a string into chunks of length n or less
by repellent (Priest) on Aug 21, 2008 at 17:00 UTC
Re: How to split a string into chunks of length n or less
by isync (Hermit) on Aug 21, 2008 at 18:38 UTC
    Thanks monks- for the in depth discussion and help!