Gary Gary - 4 months ago 12
Perl Question

Global Substitution

Hi I am using the below code to replace date formats but I am unable to figure out how to globally change all dates. Currently, the script finds and replaces the dates correctly, but it only does it for the first date found within a line but skips the rest of that line. So if there is another date that needed to be change within the same line it ignores it. I've attempted using global substitution but to no avail. If anyone could give me an idea I would very much appreciate it.

use strict;
use Time::Piece ();

my $file = $ARGV[0];
open FILE, $file or die;


while ( my $line = <FILE> ) {
chomp $line;
my ($date) = $line =~ m/([A-Z][a-z][a-z] [ \d]{2} \d{4} \d{2}:\d{2}[AP]M)/;

if ($date eq ''){
print "$line\n";
next;
}
my $new_dt = Time::Piece->strptime($date, '%b %d %Y %H:%M%p')->strftime('%Y-%m-%d %H:%M:%S');

$line =~ s/$date/$new_dt/g;
print "$line\n";
}

close FILE;
print "\n";


EDIT: Added example

Input:

May 15 2007 12:00AM, , 1, 0, Feb 2 2003 12:00PM

Output:

2007-05-15 00:00:00, , 1, 0, Feb 2 2003 12:00PM

Answer

You are replacing all the datetimes that are identical to the first datetime of the line. You don't even try to find any other datetimes.

while (<>) {
    s{([A-Z][a-z][a-z] [ \d]\d \d{4} \d{2}:\d{2}[AP]M)}{
        Time::Piece->strptime($1, '%b %d %Y %I:%M%p')->strftime('%Y-%m-%d %H:%M:%S')
    }eg;

    print;
}

As it turns out, the subject you chose for your question was quite appropriate :)


Note: I changed %H (hour as 0..23) to the more appropriate than %I (hour as 1..12).