2

I have bunch of text and I am trying to match a group of pattern, the regex which I am using is able to match the pattern but the problem is that it matches only the second group not the first group.

open(FILE, "match.txt") || die("Could not open file ");
my $text = do { local $/; <FILE> };

while( $text =~ m/FibreChannel SCSI Interface.*World Wide Port Number\.*(.*?)\n.*Driver\.+(.*?)\n.*Vendor Name\.+(.*?)\n/sgmp )
{
    print "$1\n$2\n$3\n";
}

Prints

0x1b201
lpfc_740
Test Corporation

The above code works but it displays only the text from the second group not the first group. What am I missing here? Is there a better way to do this?

I thought it would print

0x1a101
lpfc_740
Test Corporation
0x1b201
lpfc_740
Test Corporation

------------------------ match.txt contains

\==+FibreChannel SCSI Interface : 
        |----Link State.........................................Down
        |----World Wide Port Number.............................0x1a101
        \==+SCSI Interface : 
           |----Driver..........................................lpfc_740
           |----Queue Depth.....................................2038 
           \==+PCI Device : 
              |----Bus..........................................0x06 
              |----Vendor Name..................................Test Corporation
              |----Slot Description.............................

\==+FibreChannel SCSI Interface : 
        |----Link State.........................................Down
        |----World Wide Port Number.............................0x1b201
        \==+SCSI Interface : 
           |----Driver..........................................lpfc_740
           |----Queue Depth.....................................2038 
           \==+PCI Device : 
              |----Bus..........................................0x0a 
              |----Vendor Name..................................Test Corporation
              |----Slot Description.............................          
0

2 Answers 2

5

The problem is that the first .* is greedily matching as much as it can without preventing a match; so, it swallows everything up until the second World Wide Port Number. You need to change it to .*?, like you're already using elsewhere in your pattern. (And, similarly for other instances of .*.)

Sign up to request clarification or add additional context in comments.

3 Comments

I changed .* to .*? for all the instances and now I get the first group not the second group. I still cannot figure out why I cannot get both the groups.
Are you sure you've changed it in all three places? Since your $2 and $3 look the same in both groups, leaving .* intact in just one place will make it look like only the first group is being matched, when in fact, your regex is really matching both groups together.
ruakh, you are a god among men. Thanks it worked, I knew I was doing some silly mistake but could not figure out what.
0

Here's how it should be

$text =~ m/FibreChannel SCSI Interface.*?World Wide Port Number\.*([a-z0-9]+).*?Driver\.+(\w+).*?Vendor Name\.+([a-zA-Z ]+).*?\n/sgmp

1 Comment

Thanks Devendra, this works too, I added ruakh's comments in my code and now its working.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.