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

Hello, monks! I am starting my third week of Perl experience. Coming from a (limited) C++ background, I am fascinated with the ease and potency of regular expressions. But now I have run into something I don't think regexes can solve.

The problem: I have a number of strings composed of a hodgepodge of information - dates, times, comments, other numbers, etc. I am trying to replace some of the dates with their epoch timestamps.

Thus far:

Where I'm stuck: I'm not sure how to get the timestamp back into the appropriate string in the proper place(s). I have tried using a subroutine with search and replace, i.e. s/<regex to find date>/&<subroutine to calculate date's timestamp>/ge, but I continue to get syntax errors (I assume because you can't call subroutines inside a regex).

Thoughts on how to proceed:

  1. This would be easily solved if I could find essentially a "search, modify, replace" function or something similar. I'm only assuming one cannot call subroutines inside s/ / / because I am getting errors trying to do so - if it is indeed possible, please correct me - and maybe provide a dummy example too please. ^_^
  2. I guess I could also completely rebuild the strings, i.e. breakup every field (into an array), modify the ones I need to, and then reassemble the string. It just seems tedious and messy. I wanted to check with some more experienced folks to make sure I wasn't doing a lot of silly and unnecessary work.

Thanks!

Replies are listed 'Best First'.
Re: Search, modify, replace?
by ikegami (Patriarch) on Jun 10, 2009 at 14:59 UTC

    You want to make changes, so you want the substitution operator (s///). And you want the replacement to be the result of a Perl expression, so you need to use the "e" modifier.

    use Time::Local qw( timelocal ); s/(\d{4})-(\d{2})-(\d{2})/ timelocal(0,0,0, $3,$2-1,$1) /ge;

    but I continue to get syntax errors (I assume because you can't call subroutines inside a regex).

    Maybe there's something wrong with the bits you omitted (like an unescaped "/"?) since the bits you did post are fine. Next time, please post the actual code and error messages.

    Well, except that you're using "&" on your function call. Why are you telling Perl to ignore prototypes?

Re: Search, modify, replace?
by JavaFan (Canon) on Jun 10, 2009 at 15:03 UTC
    I'm not sure how to get the timestamp back into the appropriate string in the proper place(s). I have tried using a subroutine with search and replace, i.e.s/<regex to find date>/&<subroutine to calculate date's timestamp>/ge, but I continue to get syntax errors (I assume because you can't call subroutines inside a regex).
    You don't have the subroutine inside the regex, and you don't have to. Your approach is sound. So the syntax error must be in the details. Which you did't post.
Re: Search, modify, replace?
by Timjc86 (Novice) on Jun 10, 2009 at 15:28 UTC

    Thank you all for your speedy replies, I really appreciate it.

    ikegami, that looks like exactly what I was looking for, thank you. I'm not sure why I never realized I could directly call timelocal() inside s///. I also did not properly understand the $1, $2, etc. special variables, but that example illustrates their use perfectly.

    Well, except that you're using "&" on your function call. Why are you telling Perl to ignore prototypes?
    The "&" was my attempt to call a subroutine inside the s///. My thought process was to have the subroutine do the work of appropriately arranging the date elements (day, month, year, etc), calling timelocal(), and returning the epoch timestamp. I have a knack for over-complicating my own code. =) I'm also still learning with regexes in general - I don't yet remember all of the characters that have special meanings inside a regex (as it sounds like "&" does: to ignore prototypes?).

    I will give this a shot. Thanks again everyone.

      I don't yet remember all of the characters that have special meanings inside a regex (as it sounds like "&" does: to ignore prototypes?).
      The  & (ampersand) character is not a regular expression metacharacter, i.e., it has no special meaning in a regex.

      The  & sigil does have a special meaning with respect to subroutine invocation. See perlsub and search for '&', especially in the first part of the DESCRIPTION section.

Re: Search, modify, replace?
by Utilitarian (Vicar) on Jun 10, 2009 at 15:02 UTC
    Never mind, forgot about the e modifier