Re: Using sprintf in regular expreession.
by jwkrahn (Abbot) on Feb 02, 2022 at 19:53 UTC
|
$date=~ s/(\d+)-(\d+)-(\d+)/ sprintf( "%d-\/%02d\/-%d", $3, $1, $2
+)/ge;
| [reply] [d/l] |
Re: Using sprintf in regular expreession.
by rsFalse (Chaplain) on Feb 02, 2022 at 20:12 UTC
|
s/PATTERN/REPLACEMENT/msixpodualngcer:
>> e Evaluate the right side as an expression.
The whole right side of the regex is evaluated.
You can't make some parts of the REPLACEMENT evaluated and some not. So you should wrap "$3-" and "-$2" in doublequotes and join all parts by concatenation, e.g.:
$date =~ s/(\d+)-(\d+)-(\d+)/ "$3-" . sprintf("%02d",$1) . "-$2" /ge;
Upd. You need double quotes to interpolate $3 and $2 (single quotes won't).
| [reply] [d/l] [select] |
|
Great explanation! See jwkrahn (above) for a simpler form of the required expression.
| [reply] |
Re: Using sprintf in regular expreession.
by Fletch (Bishop) on Feb 02, 2022 at 20:41 UTC
|
Also not directly relevant because you've got them because of your misuse of /e, but in general if you need to use slashes in a match or substitution it's generally cleaner to use an alternate delimiter (or matched pair of delimiters) like s{MATCH}{REPLACE} instead to reduce the amount of backwhacking you need to do.
The cake is a lie.
The cake is a lie.
The cake is a lie.
| [reply] [d/l] [select] |
Re: Using sprintf in regular expression.
by hippo (Bishop) on Feb 03, 2022 at 11:23 UTC
|
use strict;
use warnings;
use Time::Piece;
use Test::More tests => 1;
my $date = '3-15-1932';
my $want = '1932-03-15';
my $have = Time::Piece->strptime ($date, '%m-%d-%Y')->date;
is $have, $want;
| [reply] [d/l] |
Re: Using sprintf in regular expreession.
by johngg (Canon) on Feb 02, 2022 at 22:22 UTC
|
Rather than using regular expressions and substitution you could split on hyphens into a list which you then slice into the order required. Pass the re-ordered items through a map in which you apply the sprintf and then join it all up again. Perhaps a bit more long winded but, to my eyes, a little easier to see what's going on.
johngg@abouriou:~/go$ perl -Mstrict -Mwarnings -E 'say q{};
my $date = q{3-15-1932};
$date =
join q{-},
map { sprintf q{%02d}, $_ }
( split q{-}, $date )[ 2, 0, 1 ];
say $date;'
1932-03-15
I hope this is of interest.
| [reply] [d/l] |
|
> Perhaps a bit more long winded
IMHO, you are overcomplicating it. sprintf can take a list of values, no need for a map.
It can even rearrange the order, tho I prefer the slice here.
| [reply] |
|
DB<23> $date = "3-15-1932"
#### split and slice
DB<24> printf "% 4d-%02d-%02d", (split /-/, $date)[2,0,1]
1932-03-15
#### match list
DB<25> printf "% 4d-%02d-%02d", ($date =~ /(\d+)-(\d+)-(\d+)/ )[2,0,
+1]
1932-03-15
#### reorder printf with 3$
DB<26> printf "%3\$ 4d-%02d-%02d", split /-/, $date
1932-03-15
#### classic
DB<27> printf "% 4d-%02d-%02d",$3,$1,$2 if $date =~ /(\d+)-(\d+)-(\d
++)/
1932-03-15
| [reply] [d/l] |
Re: Using sprintf in regular expreession.
by Marshall (Canon) on Feb 05, 2022 at 08:11 UTC
|
Since this is Perl and there is always more than one way.... you can use 2 regexes and then you don't need sprintf. I don't know which actually executes faster.
Code follows showing these cases..
a. could use one regex to handle 2 digit day, another for 1 digit day
b. probably better is to handle single digit day, then swap order instead of combining the replace and swap
c. doesn't handle single digit month, so could use a 3rd regex to fix that
d. finally, could fix any single digit and then swap order
use strict;
use warnings;
my $x='11-3-1936';
$x=~ s/(\d+)-(\d\d)-(\d+)/$3-$1-$2/; #2 digit day
$x=~ s/(\d+)-(\d)-(\d+)/$3-$1-0$2/; #1 digit day
print "$x\n"; # 1936-11-03
$x='2-5-1966';
$x=~ s/(\d+)-(\d)-(\d+)/$1-0$2-$3/; # fix 1 digit day
$x=~ s/(\d+)-(\d+)-(\d+)/$3-$1-$2/; # swap order
print "$x\n"; # 1966-2-05 doesn't fix single digit month
$x='2-5-1966';
$x=~ s/(\d+)-(\d)-(\d+)/$1-0$2-$3/; # fix 1 digit day
$x=~ s/(\d)-(\d+)-(\d+)/0$1-$2-$3/; # fix 1 digit month
$x=~ s/(\d+)-(\d+)-(\d+)/$3-$1-$2/; # swap order
print "$x\n"; # 1966-02-05 ok, but uses 3 regexes
$x='2-5-1966';
$x=~ s/\b(\d)\b/0$1/g; # fix any single digit
$x=~ s/(\d+)-(\d+)-(\d+)/$3-$1-$2/; # swap order
print "$x\n" # 1966-02-05
| [reply] [d/l] |
Re: Using sprintf in regular expreession.
by perlfan (Vicar) on Feb 04, 2022 at 06:00 UTC
|
A. that's super funky use of sprintf
B. you really need to take a look at POSIX::strftime and it's red headed brother, POSIX::strptime. Both give you the same feels as sprintf if that's what you're needing
I mark my journey as a programmer by moments of sheer awe when I discover something awesome. That combo is one of those times. The other was when I first learned to create a mailto: link in my college computer lab in the 90s. These 2 events were roughtly 19 years apart and the ones that stick out most in my mind. Good luck. | [reply] [d/l] [select] |