Replace an occurrence of a regexp with a function call on a substringof the match, multiple times on

Discussion in 'Perl Misc' started by David Karr, Sep 16, 2013.

  1. David Karr

    David Karr Guest

    I have a pattern in an input file that looks like this:

    latestTime="1379353492000"

    I need to replace this with something like this:

    latestTime="2013-09-16 10:34:33"

    This pattern will occur in multiple lines in a file, and multiple times on a single line.

    The hardest part of this seems to be to pass the milliseconds value into "strftime" as the replacement portion of the substitution regexp, for each occurrence. I can't get this to work.

    This is what I have so far, and I hope I don't have to use that very strange syntax to call a function in the string (I found some references with examples like this):

    #! /bin/perl
    use English;
    use strict;
    use POSIX qw( strftime );

    $| = 1;

    while (my $line = <STDIN>) {
    if ($line =~ /(^.*latestTime=")([0-9]+)(".*$)/) {
    "\n";
    $line =~ s/latestTime="([0-9]+)"/latestTime="${\strftime("%Y-%m-%d %H:%M:%S", localtime($1/1000))}"/g';
    }
    print $line;
    }
     
    David Karr, Sep 16, 2013
    #1
    1. Advertising

  2. Re: Replace an occurrence of a regexp with a function call on a substring of the match, multiple times on the line, multiple lines in a file

    David Karr <> writes:

    > I have a pattern in an input file that looks like this:
    >
    > latestTime="1379353492000"
    >
    > I need to replace this with something like this:
    >
    > latestTime="2013-09-16 10:34:33"
    >
    > This pattern will occur in multiple lines in a file, and multiple
    > times on a single line.
    >
    > The hardest part of this seems to be to pass the milliseconds value
    > into "strftime" as the replacement portion of the substitution regexp,
    > for each occurrence. I can't get this to work.
    >
    > This is what I have so far, and I hope I don't have to use that very
    > strange syntax to call a function in the string (I found some
    > references with examples like this):
    >
    > #! /bin/perl
    > use English;
    > use strict;
    > use POSIX qw( strftime );
    >
    > $| = 1;


    You probably don't need this (if you do, nothing in your problem
    description suggest that you do). Also, since you "use English" it's
    odd to then use the cryptic name for this variable. It's
    $OUTPUT_AUTOFLUSH with "use English".

    > while (my $line = <STDIN>) {
    > if ($line =~ /(^.*latestTime=")([0-9]+)(".*$)/) {


    You don't have to match the lines first -- just try the substitution you
    want to do. Also, Perl has \d with is often better than writing [0-9].

    > "\n";
    > $line =~ s/latestTime="([0-9]+)"/latestTime="${\strftime("%Y-%m-%d %H:%M:%S", localtime($1/1000))}"/g';


    You can use the "e" modifier to permit an expression in a substitution,
    and you can put the whole text into strftime's format to get a simpler
    expression:

    $line =~ s!latestTime="(\d+)"!
    strftime("latestTime=\"%Y-%m-%d %H:%M\"",
    localtime($1/1000))!eg;

    Because it's an expression, you can be free with the layout.

    > }
    > print $line;
    > }


    Finally, this pattern of looping and printing is so common that Perl
    provides a command-line options for it. You can therefore write this
    sort of thing as a single command, should that be more convenient than a
    script:

    perl -MPOSIX -pe 's/\d+/strftime("%F", localtime($1))/eg'

    (using a simplified example).

    --
    Ben.
     
    Ben Bacarisse, Sep 16, 2013
    #2
    1. Advertising

  3. David Karr

    David Karr Guest

    Re: Replace an occurrence of a regexp with a function call on asubstring of the match, multiple times on the line, multiple lines in a file

    On Monday, September 16, 2013 12:02:05 PM UTC-7, Ben Bacarisse wrote:
    > David Karr <> writes:
    >
    >
    >
    > > I have a pattern in an input file that looks like this:

    >
    > >

    >
    > > latestTime="1379353492000"

    >
    > >

    >
    > > I need to replace this with something like this:

    >
    > >

    >
    > > latestTime="2013-09-16 10:34:33"

    >
    > >

    >
    > > This pattern will occur in multiple lines in a file, and multiple

    >
    > > times on a single line.

    >
    > >

    >
    > > The hardest part of this seems to be to pass the milliseconds value

    >
    > > into "strftime" as the replacement portion of the substitution regexp,

    >
    > > for each occurrence. I can't get this to work.

    >
    > >

    >
    > > This is what I have so far, and I hope I don't have to use that very

    >
    > > strange syntax to call a function in the string (I found some

    >
    > > references with examples like this):

    >
    > >

    >
    > > #! /bin/perl

    >
    > > use English;

    >
    > > use strict;

    >
    > > use POSIX qw( strftime );

    >
    > >

    >
    > > $| = 1;

    >
    >
    >
    > You probably don't need this (if you do, nothing in your problem
    >
    > description suggest that you do). Also, since you "use English" it's
    >
    > odd to then use the cryptic name for this variable. It's
    >
    > $OUTPUT_AUTOFLUSH with "use English".


    Write Perl without cryptic syntax? What? :)

    Thanks for the more expressive way to do this, and reminding me that I don't need it for this script.

    > > while (my $line = <STDIN>) {

    >
    > > if ($line =~ /(^.*latestTime=")([0-9]+)(".*$)/) {

    >
    >
    >
    > You don't have to match the lines first -- just try the substitution you
    >
    > want to do. Also, Perl has \d with is often better than writing [0-9].
    >
    >
    >
    > > "\n";

    >
    > > $line =~ s/latestTime="([0-9]+)"/latestTime="${\strftime("%Y-%m-%d %H:%M:%S", localtime($1/1000))}"/g';

    >
    >
    >
    > You can use the "e" modifier to permit an expression in a substitution,
    >
    > and you can put the whole text into strftime's format to get a simpler
    >
    > expression:
    >
    >
    >
    > $line =~ s!latestTime="(\d+)"!
    >
    > strftime("latestTime=\"%Y-%m-%d %H:%M\"",
    >
    > localtime($1/1000))!eg;
    >
    >
    >
    > Because it's an expression, you can be free with the layout.


    Outstanding. The "e" directive is definitely new to me. I'll have to read about that.

    > > }

    >
    > > print $line;

    >
    > > }

    >
    >
    >
    > Finally, this pattern of looping and printing is so common that Perl
    >
    > provides a command-line options for it. You can therefore write this
    >
    > sort of thing as a single command, should that be more convenient than a
    >
    > script:
    >
    >
    >
    > perl -MPOSIX -pe 's/\d+/strftime("%F", localtime($1))/eg'


    I'm writing this as a command-line filter tool, to be used with other filters, so I want the details in the script, not on the command line, but thanks for that option ayway.

    > (using a simplified example).
    >
    >
    >
    > --
    >
    > Ben.
     
    David Karr, Sep 16, 2013
    #3
  4. David Karr

    David Karr Guest

    Re: Replace an occurrence of a regexp with a function call on asubstring of the match, multiple times on the line, multiple lines in a file

    On Monday, September 16, 2013 12:02:05 PM UTC-7, Ben Bacarisse wrote:
    > David Karr <> writes:
    > You can use the "e" modifier to permit an expression in a substitution,
    >
    > and you can put the whole text into strftime's format to get a simpler
    >
    > expression:
    >
    > $line =~ s!latestTime="(\d+)"!
    > strftime("latestTime=\"%Y-%m-%d %H:%M\"",
    > localtime($1/1000))!eg;
    >
    > Because it's an expression, you can be free with the layout.


    I find this "e" directive curious. I can't find this documented anywhere. Is there a good reference for that?
     
    David Karr, Sep 16, 2013
    #4
  5. Re: Replace an occurrence of a regexp with a function call on a substring of the match, multiple times on the line, multiple lines in a file

    David Karr <> writes:

    > On Monday, September 16, 2013 12:02:05 PM UTC-7, Ben Bacarisse wrote:
    >> David Karr <> writes:
    >> You can use the "e" modifier to permit an expression in a substitution,

    <snip>
    > I find this "e" directive curious. I can't find this documented
    > anywhere. Is there a good reference for that?


    It's documented in "perlop" as part of the documentation of s///.
    Technically it's called a modifier or an option (the latter was a
    surprise to me but it's one of the terms used in the documentation).

    --
    Ben.
     
    Ben Bacarisse, Sep 16, 2013
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Registered User

    Find first occurrence of string and replace

    Registered User, Oct 16, 2006, in forum: C Programming
    Replies:
    6
    Views:
    492
    Ed Collins
    Oct 18, 2006
  2. Jack Steven
    Replies:
    2
    Views:
    465
    Chris Rebert
    Mar 9, 2009
  3. John Gordon
    Replies:
    13
    Views:
    503
    Ian Kelly
    Dec 20, 2011
  4. Old Echo
    Replies:
    1
    Views:
    195
    Adam Shelly
    Sep 4, 2008
  5. Replies:
    12
    Views:
    460
    Ben Morrow
    Jul 9, 2008
Loading...

Share This Page