Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

splitting a string into arbitrary lengths

by ryanc (Monk)
on Jun 22, 2005 at 21:17 UTC ( [id://469186]=perlquestion: print w/replies, xml ) Need Help??

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

greetings monks,

let's say I have a variable containing a date, for instance:
$today = '20050622';
and I want to chop it up into three more variables along the lines of year,
month, and day. I know I can do this pretty simply with substr(), like this:
$tyear = substr($today, 0, 4); $tmon = substr($today, 4, 2); $tday = substr($today, 6, 2);
but I'm looking for something a little more elegant, like using split in a one liner :).

any ideas?

thanks.
ryanc

Replies are listed 'Best First'.
Re: splitting a string into arbitrary lengths
by rev_1318 (Chaplain) on Jun 22, 2005 at 21:36 UTC
    Try unpack:
    ($tyear, $tmon, $tday) = unpack("a4a2a2", $today);

    Paul

      ahh, very nice...thanks!

        (un)pack will likely be the fastest way to do this. Don't forget you can put spaces in appropriate places in the pattern to make it easier to read. (I say 'pack' because the useful documentation for 'unpack' is in 'pack'. :-)

        ---
        $world=~s/war/peace/g

Re: splitting a string into arbitrary lengths
by kirbyk (Friar) on Jun 22, 2005 at 21:34 UTC
    You could do it with a regex as well:
    my ($tyear, $tmon, $tday) = ($today =~ /(\d{4})(\d{2})(\d{2})/);
    This would be a good route if you had a less standard format, like optional dashes.

    -- Kirby, WhitePages.com

      That is what I'd perhaps use too, depending on the application. If I'd chose this way I'd even tag along a success check (and add anchors). Your format may change some day and then you'll be glad you caught that.

      my ($y, $m, $d) = $today =~ /^(\d\d\d\d)(\d\d)(\d\d)\z/ or die "Incorrect date format: '$today'";

      ihb

      See perltoc if you don't know which perldoc to read!

Re: splitting a string into arbitrary lengths
by bmann (Priest) on Jun 22, 2005 at 21:40 UTC
    unpack

    my ($tyear, $tmon, $tday) = unpack( 'A4A2A2', '20050622' );

    If you choose to use this, you might also want to read pack and perlpacktut

Re: splitting a string into arbitrary lengths
by moot (Chaplain) on Jun 22, 2005 at 21:32 UTC
    How's about:
    my ($y, $m, $d) = $today =~ /(\d){4}(\d){2}(\d){2}/;
    ..although as a previous poster mentioned, you might lose a little in readability.

    Now hiring in Atlanta. /msg moot for details.
      my ($y, $m, $d) = $today =~ /(\d){4}(\d){2}(\d){2}/;

      ..although as a previous poster mentioned, you might lose a little in readability.

      You will want to move the closing parens to after the quantifiers for each group of digits, or you'll lose more than just readability ;)

      As written, the regex will only capture the last digit in each group.

      my $today = 20050622; my ($y, $m, $d) = $today =~ /(\d){4}(\d){2}(\d){2}/; print join ":", $y, $m, $d; # prints 5:6:2, not 2005:06:22
        crap, you're right. good catch.

        --
        Now hiring in Atlanta. /msg moot for details.

Use a date module :)
by mugwumpjism (Hermit) on Jun 23, 2005 at 00:36 UTC

    If you're splitting a date into its components, why not use a Date module?

    use Time::Piece; my $time = Time::Piece->strptime("20050622", "%Y%m%d"); my ($tyear, $tmon, $tday) = ($time->year, $time->mon, $time->mday)

    Ok, it's not quite as small as a straight regex match, but quite often when you are playing with dates manually like this, it pays to use a module like Time::Piece, DateTime or even Date::Manip. The advantages now don't seem worth it - but as you start to work with dates more, you'll appreciate having objects for them so you can do calculations on them without missing things.

    $h=$ENV{HOME};my@q=split/\n\n/,`cat $h/.quotes`;$s="$h/." ."signature";$t=`cat $s`;print$t,"\n",$q[rand($#q)],"\n";
Re: splitting a string into arbitrary lengths
by BazB (Priest) on Jun 22, 2005 at 21:25 UTC

    There's nothing wrong with what you're doing; anything else is likely to simply be obfuscation.


    If the information in this post is inaccurate, or just plain wrong, don't just downvote - please post explaining what's wrong.
    That way everyone learns.

      obfuscated code welcomed.
Re: splitting a string into arbitrary lengths
by ank (Scribe) on Jun 23, 2005 at 00:35 UTC

    How about a regexp, but using the /x modifier:

    my ($tyear, $tmon, $tday) = ($today =~ /^(\d{4}) # 4 digit year (\d{2}) # 2 digit month (\d{2})$/x); # 2 digit day

    -- ank

Re: splitting a string into arbitrary lengths
by planetscape (Chancellor) on Jun 23, 2005 at 17:47 UTC
      I actually was doing this at first but the program I'm writing has to be as portable as
      possible, so I'm trying to avoid the inclusion of all but the absolute necessary modules.

      thanks. ryanc

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://469186]
Approved by moot
Front-paged by grinder
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others meditating upon the Monastery: (4)
As of 2024-04-19 11:30 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found