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

Dear Monks , i have a problem with regex, i have to warn you i am fairly newbie in perl (but i love it). My problem is that i have to extract some info from a mail subject like this --RV: vRealize Operations Manager new alert Type:Virtualization/Hypervisor, Sub-Type:Availability, State:critical, Object Type:VMwareAdapter Instance, Name:HOSTVCENTER01 from 192.168.1.121--- I have to recover by example , the Name, event, etc

my $host = $string =~ /((?<=Name:)[^ ]+)?/; my $event = $string =~ /((?<=Manager] )[^ ]+)/;

But when i print the variable i only get 1 , i checked the regex in all the regex checkers , and look fine. any idea of what i am doing wrong?

Replies are listed 'Best First'.
Re: problem with regex
by haukex (Archbishop) on Dec 13, 2016 at 19:00 UTC

    Hi zerodmg,

    See the discussion of m/PATTERN/ in Regexp Quote Like Operators: In scalar context, $string=~/.../ returns true/false for whether the match succeeded or not, in list context it returns the capture groups (unless you use the /g modifier, then the return value is different). The latter is what tybalt89 is showing you in the example, putting parens around the variable(s) in a my ($x) = ... assignment causes the right side to be evaluated in list context.

    Hope this helps,
    -- Hauke D

      Thank you Hauke D!

Re: problem with regex
by tybalt89 (Monsignor) on Dec 13, 2016 at 18:51 UTC
    my ($host) = $string =~ /((?<=Name:)[^ ]+)?/; my ($event) = $string =~ /((?<=Manager] )[^ ]+)/;

      Thank you tybalt89!

Re: problem with regex
by kcott (Archbishop) on Dec 14, 2016 at 04:58 UTC

    G'day zerodmg,

    Welcome to the Monastery.

    I see you've got a solution to your immediate problem. My post suggests an alternative way of extracting the same data.

    Instead of performing multiple matches on the same string, you could do all the matches, and collect all the data, in one pass using alternating named captures. These were introduced in v5.10 (perl5100delta: Named Capture Buffers) so you'll need at least that version of Perl.

    Here's some example code with three test subjects: your original; your original with some fields in different positions; and your original with some fields missing. Note that the data is output in the same order regardless of the order it appears in the subject line: this is useful not just for simple output, as I have here, but also in many other situations, such as writing to a CVS file, displaying in an HTML table, using in an SQL insert statement, and so on. Also note that missing data elements are identified and highlighted.

    #!/usr/bin/env perl use 5.010; use strict; use warnings; my @test_subjects = ( '--[RV: vRealize Operations Manager] new alert Type:Virtualization +/Hypervisor, Sub-Type:Availability, State:critical, Object Type:VMwar +eAdapter Instance, Name:HOSTVCENTER01 from 192.168.1.121---', '--[RV: vRealize Operations Manager] new State:critical, Object Ty +pe:VMwareAdapter Instance, alert Type:Virtualization/Hypervisor, Sub- +Type:Availability, Name:HOSTVCENTER01 from 192.168.1.121---', '--[RV: vRealize Operations Manager] new alert Type:Virtualization +/Hypervisor, State:critical, Name:HOSTVCENTER01 from 192.168.1.121--- +', ); my $subject_re = qr{(?x: (?> Manager ] \s+ (?<event> \S+ ) | alert \s Type: (?<type> [^,]+ ) | Sub-Type: (?<subtype> [^,]+ ) | State: (?<state> [^,]+ ) | Object \s Type: (?<object> [^,]+ ) | Name: (?<host> \S+ ) | from \s+ (?<from> [0-9.]+ ) ) )}; my @fields = qw{event type subtype state object host from}; my $format = '%-' . (length((sort { length $b <=> length $a } @fields)[0]) + +1) . "s %s\n"; my $pre_subject = '=== Subject ' . '=' x 30; my $post_subject = '=' x 42; my %empty; @empty{@fields} = ('Not supplied!') x @fields; for my $subject (@test_subjects) { my %captured; while ($subject =~ /$subject_re/g) { $captured{$_} = $+{$_} for keys %+; } my %found = (%empty, %captured); say for $pre_subject, $subject, $post_subject; printf $format, "$_:", $found{$_} for @fields; }

    Here's the output:

    === Subject ============================== --[RV: vRealize Operations Manager] new alert Type:Virtualization/Hype +rvisor, Sub-Type:Availability, State:critical, Object Type:VMwareAdap +ter Instance, Name:HOSTVCENTER01 from 192.168.1.121--- ========================================== event: new type: Virtualization/Hypervisor subtype: Availability state: critical object: VMwareAdapter Instance host: HOSTVCENTER01 from: 192.168.1.121 === Subject ============================== --[RV: vRealize Operations Manager] new State:critical, Object Type:VM +wareAdapter Instance, alert Type:Virtualization/Hypervisor, Sub-Type: +Availability, Name:HOSTVCENTER01 from 192.168.1.121--- ========================================== event: new type: Virtualization/Hypervisor subtype: Availability state: critical object: VMwareAdapter Instance host: HOSTVCENTER01 from: 192.168.1.121 === Subject ============================== --[RV: vRealize Operations Manager] new alert Type:Virtualization/Hype +rvisor, State:critical, Name:HOSTVCENTER01 from 192.168.1.121--- ========================================== event: new type: Virtualization/Hypervisor subtype: Not supplied! state: critical object: Not supplied! host: HOSTVCENTER01 from: 192.168.1.121

    [Aside: You'll note that in your post, what you intended to be "[vRealize Operations Manager]", appears as a link without the brackets. This is one way that you can create links (see "What shortcuts can I use for linking to other information?"). If you actually want the brackets displayed, use &#91; for [ and &#93; for ]; alternatively, put the whole subject line within <code>...</code> tags which, in this instance, would have been a better option as it allows us to download a verbatim copy of your data (see "Writeup Formatting Tips"). You can edit your post to fix this (see "How do I change/delete my post?").]

    — Ken

      Thank you Ken! what a impressive response! i am just a newbie in perl but never have in any other group a response like that! wow such courtesy and quickness! really all of you thank you! you make the world a better place. p.s. i am not natural in english so my grammar could hurt you.

        You're very welcome. I'm always happy to help and encourage those who write things like: "i am fairly newbie in perl (but i love it)". I hope you continue to enjoy coding in Perl.

        — Ken