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

Hello Monks, I am trying to extract dates/times and email addresses from a log file. the format is like this: 2011-01-01 15:34:554 some words and numbers then email@host.com I would like to print the date, time, email address. I have something that is printing the email address but I cannot seem to be able to get the other 2 fields that i need. Kindly help when you get a moment. thanks, Jose. this is what i have

while (my $line = <>) { foreach my $output (split /\s+/, $line) { if ($output =~ /^[-\w.]+@([a-z0-9][a-z-0-9]+\.)+[a-z]{ +2,4}$/i) { print $output . "\n";

Replies are listed 'Best First'.
Re: matching multiple patterns in one line
by toolic (Bishop) on Nov 18, 2015 at 17:49 UTC
    Assuming the date, time, email address have no whitespace:
    use warnings; use strict; my $line = '2011-01-01 15:34:554 some words and numbers then email@hos +t.com'; my @tokens = split /\s+/, $line; print join ' ', @tokens[0..1,-1], "\n"; __END__ 2011-01-01 15:34:554 email@host.com
Re: matching multiple patterns in one line
by james28909 (Deacon) on Nov 18, 2015 at 18:40 UTC
    # should work no matter where date, time, or email address is located +in current line my $line = '2011-01-01 15:34:554 some words and numbers then email@hos +t.com'; my @lines = split(/\s+/, $line); for(@lines){ print $_ . "\n" if /[0-9]{4}[-][0-9]{2}[-][0-9]{2}|[0-9]{1,2}[:][0-9]{ +1,2}[:][0-9]{1,3}|[@]/; }
    EDIT: Updated regex to be slightly more dynamic for 'time'

      On a side note, how could i put my sample above on one line? I mean without for(@lines){print ...};

      How could i make it in one line, as in 'print $_ . "\n" /stuff to match in @lines/ for(@lines)'?

        Adapting toolic's approach above:

        c:\@Work\Perl\monks>perl -wMstrict -le "my $line = '2011-01-01 15:34:554 some words and numbers then email@ho +st.com'; printf qq{date '%s' time '%s' email '%s' \n}, (split /\s+/, $line)[0, + 1, -1]; " date '2011-01-01' time '15:34:554' email 'email@host.com'
        But why do you care that it's on one line and/or without a for-loop?

        Update: Or, if you want to go the regex route:

        c:\@Work\Perl\monks>perl -wMstrict -le "my $rx_d = qr{ \d{4} - \d\d - \d\d }xms; my $rx_t = qr{ \d\d : \d\d : \d\d }xms; my $rx_e = qr{ \S+ }xms; ;; my $line = qq{2011-01-01 15:34:55 blah blah yada email\@host.com\n}; print qq{[$line]}; printf qq{d '%s' t '%s' e '%s' \n}, $line =~ m{ \A ($rx_d) \s+ ($rx +_t) .*? ($rx_e) \s* \z }xms; " [2011-01-01 15:34:55 blah blah yada email@host.com ] d '2011-01-01' t '15:34:55' e 'email@host.com'
        I suppose the definitions of all the  qr// regex objects make this more than one line, but that's life. Also, I hope you can come up with a better e-mail address regex than mine.


        Give a man a fish:  <%-{-{-{-<

        One way that seems to do what you're looking for:

        print "$_\n" for grep {$_ =~ /$regex/} @lines;