Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

one liner string extraction

by natxo (Scribe)
on Nov 02, 2017 at 11:15 UTC ( [id://1202601]=perlquestion: print w/replies, xml ) Need Help??

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

hi, I need to get a string from a line matching the last occurrence of another string in a log file. I can get the last occurrence of in the log file like this:

perl -ne '$string=$_ if /Successfully sent/; END{print $string}' $log +file
The line something like this:
2017-11-02 12:08:11,120 INFO [Timer-Driven Process Thread-8] o.a.nifi. +remote.StandardRemoteGroupPort RemoteGroupPort[name=Receiver,targets= +https://host.sub.domain.tld:9443/nifi] Successfully sent [StandardFlo +wFileRecord[uuid=xxxxxxxxxxxx,claim=StandardContentClaim [resourceCla +im=StandardResourceClaim[id=xxx, container=default, section=xxx], off +set=384244, length=163820],offset=0,name=xxxxx.json,size=163820]] (15 +9.98 KB) to https://host.sub.domain.tld:9443/nifi-api in 242 millisec +onds at a rate of 660.28 KB/sec
Now I need to get just the timestamp at the beginning of this line. This is how I thought it should work:

perl -ne '$string=$_ if /Successfully sent/; $string =~ /^(.*) INFO.* +$/; END{print $1}' $logfile
But no success until now. Any tips greatly appreciated. Thanks in advance!

Replies are listed 'Best First'.
Re: one liner string extraction
by 1nickt (Canon) on Nov 02, 2017 at 11:37 UTC

    Hi, $1 is reset on each attempted match, so if a failed match occurs after your last match, $1 will be unset.

    perl -ne '$string=$_ if /Successfully sent/; $match = $1 if $string = +~ /^(.*) INFO.*$/; END{print $match}' $logfile

    Hope this helps!


    The way forward always starts with a minimal test.

      Hm-m, while the above solution works, but by way of nitpicking and because of TIMTOWTDI:

      $1 is reset on each attempted match

      $1 is reset on each successful match, and restored on each scope end. Scope end happens twice (rather, n + 1) in OP: 1st on every loop iteration (-n), second at program finishing but before executing END block(s).

      >perl -wE "'a'=~/(a)/; 'a'=~/b/; say $1" a >perl -wE "'a'=~/(a)/; 'a'=~/a/; say $1" Use of uninitialized value $1 in say at -e line 1. >perl -wE "'a'=~/(a)/; END { say $1 }" Use of uninitialized value $1 in say at -e line 1.

      But we can abuse the fact that, unlike other global variables related to regular expressions, the $^R is not dynamically scoped. Further, let's match only once, and also have a little fun and save us a few keystrokes by using a secret (END will also do, of course):

      >perl -ne "/^(.*) INFO.+Successfully sent(?{$1})/ }{ print $^R" file
      of course! Thanks, works like a charm.
Re: one liner string extraction
by kcott (Archbishop) on Nov 03, 2017 at 13:30 UTC

    G'day natxo,

    Would this be a simpler solution for what you're trying to achieve?

    $ perl -nle 'next unless /^(.*?) INFO .*? SENT/; $x = $1; END { print +$x }' ts1 INFO ... SENT ts2 INFO ... RECV ts3 INFO ... SENT ts4 INFO ... RECV ts3

    Skip unless match, otherwise save capture. Print last capture at the end.

    I used STDIN (keyboard) for dummy logfile records:

    ts1 INFO ... SENT ts2 INFO ... RECV ts3 INFO ... SENT ts4 INFO ... RECV

    Output last matching timestamp: ts3

    — Ken

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1202601]
Approved by marto
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others avoiding work at the Monastery: (3)
As of 2024-04-24 23:32 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found