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
Re: splitting a string into arbitrary lengths
by rev_1318 (Chaplain) on Jun 22, 2005 at 21:36 UTC
|
($tyear, $tmon, $tday) = unpack("a4a2a2", $today);
| [reply] [d/l] |
|
| [reply] |
|
| [reply] |
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.
| [reply] [d/l] |
|
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!
| [reply] [d/l] |
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
| [reply] [d/l] |
Re: splitting a string into arbitrary lengths
by moot (Chaplain) on Jun 22, 2005 at 21:32 UTC
|
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.
| [reply] [d/l] |
|
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
| [reply] [d/l] [select] |
|
crap, you're right. good catch.
-- Now hiring in Atlanta. /msg moot for details.
| [reply] |
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";
| [reply] [d/l] [select] |
Re: splitting a string into arbitrary lengths
by BazB (Priest) on Jun 22, 2005 at 21:25 UTC
|
| [reply] |
|
obfuscated code welcomed.
| [reply] |
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
| [reply] [d/l] [select] |
Re: splitting a string into arbitrary lengths
by planetscape (Chancellor) on Jun 23, 2005 at 17:47 UTC
|
| [reply] |
|
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
| [reply] |
|
|