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

I have a file which contains a date time stamp in the format day/month/yyyy h:m:s am or pm. I would like to do a search replace and insert date, then the time stamp back again, I would also like to figure out how to reverse the contents of a hash as my current hash is in the wrong order values,keys instead of keys,values. would something like this work?
while ( my ($key, $value) = each(%hash) ) { %copy=(my $value=>$key); }

Replies are listed 'Best First'.
Re: insert label into file
by kennethk (Abbot) on Mar 20, 2009 at 15:15 UTC

    Answering your second question, you have two syntax errors in the provided code. First, by including my in your assignment statement, you are masking the $value variable declared in your while statement (This will get caught if you use strict;use warnings). Second, you are overwriting your %copy hash on every iteration with the new key-value pair. What you mean is likely:

    use strict; use warnings; my %copy = (); while ( my ($key, $value) = each(%hash) ) { $copy{$value} = $key; }

    This can be done in one line as:

    my %copy = reverse %hash;

    Be aware that this will not behave well if you have repeat values.

    Update: This is addressed in perlfaq4.

      I have repeat values, I read this but now I don't know how to proceed.. If your hash could have repeated values, the methods above will only find one of the associated keys. This may or may not worry you. If it does worry you, you can always reverse the hash into a hash of arrays instead:
      while (($key, $value) = each %by_key) { push @{$key_list_by_value{$value}}, $key; }
      I am confused enough just using hash, hash of arrays, can I put it back into a hash somehow?, reason I want the hash is to input the data into a table in sql, using sql abstract, which looks like it should work for my purpose to store this data in a db, maybe I could somehow fix my data file to be correct by changing the way information is logged so that its numbers then names by using regexes to move the labels I have around.
        The repeat values in your hash mean that you cannot use them as primary keys for identifying a data set. Clever data structures in Perl will not help you if you are trying to use them as the keys in your database. There are a couple possible solutions here, depending on your needs. The most natural solution is to use whatever you index your database with to key your hash. Can you provide your db table structure, some sample data from your original hash and explain how they are related?
      I am still not clear on what is meant by repeat values, since I will be using some form of loop to insert the values from the hash and could actually just clobber the old and insert the new on top if I have too, since each dataset would represent a single row of data.
        The concern was exactly the clobbering. If you don't care about clobbering repeat values, then all these admonitions are irrelevant.
Re: insert label into file
by cdarke (Prior) on Mar 20, 2009 at 16:05 UTC
    Your request concerning the date/time stamp is not clear to me. I have guessed that you wish to replace the current date/time stamp with a new one showing the current date/time. Apologies if that is incorrect, please clarify what you are trying to do. Anyway, here is my guess:
    use strict; use warnings; use POSIX qw(strftime); # Open the file for read and write open (my $fh, '+<', 'data.dat') or die "Unable to open data.dat: $!"; # Specified: day/month/yyyy h:m:s am or pm # assumed dd/mm/yyyy hh:mm:ss am/pm my $new_stamp = strftime ('%d/%m/%Y %I:%M:%S %p',localtime); # This gets AM/PM insteam of am/pm, so: $new_stamp =~ s/([PA]M)$/lc $1/e; while (<$fh>) { # Replace date/time stamp with new one if (s|\d\d/\d\d/\d\d\d\d \d\d:\d\d:\d\d [ap]m|$new_stamp|) { seek ($fh,-length($_)-1, 1); print $fh $_; } } close ($fh)
      All I really want to do with the date/time is echo it back into my sql db as a date/time value, I also want to push a label into the hash so that it becomes date->timevalue, does this make sense? it seems my sql insert is thinking the date is a string.