RidRoid
RidRoid

Reputation: 961

preg_match_all with multilines not working

I have a string mystring that contains newlines in it :

when HTTP_REQUEST {
switch -glob [string tolower [HTTP::host]] {
    "sub1.sub.dom" {
    pool /networkname/hostname_80
    }
    "sub2.sub.dom" {
    pool /anothernetworkname/anotherhostname_80
    }
    default {
         drop 
    }
}
}

I'm trying to extract the pools from that string using preg_match_all but I cant get the wanted result...I'm currently using :

preg_match_all('/\/([^"]+)$/m',$mystring,$result);

the result is :

Array
(
[0] => networkname/hostname_80
    }
[1] => anothernetworkname/anotherhostname_80
    }
    default {
         drop 
    }
}
})

I have two questions :

  1. Why is the second element of the array is not similar to the first one? considering the fact that I'm using the same regex?
  2. how can I get only the pools without the braces and all the stuff behind (the regex should stop matching after the last digit of a line).

thanks.

Upvotes: 1

Views: 516

Answers (2)

Wiktor Stribiżew
Wiktor Stribiżew

Reputation: 627083

It seems you just want to extract chunks of non-whitespace chars after a word pool, 1+ whitespaces and /.

You may use

'~\bpool\h+/\K\S+$~m'

with preg_match_all function in PHP. See the regex demo.

Details

  • \bpool - a whole word pool (the next char should be a horizontal whitespace and \b is a word boundary)
  • \h+ - 1+ horizontal whitespace chars
  • / - a / char
  • \K - match reset operator to discard the text matched so far
  • \S+ - 1+ chars other than whitespace
  • $ - end of line (due to m modifier).

PHP demo:

$re = '~\bpool\h+\K/\S+$~m';
$str = "when HTTP_REQUEST {\nswitch -glob [string tolower [HTTP::host]] {\n    \"sub1.sub.dom\" {\n    pool /networkname/hostname_80\n    }\n    \"sub2.sub.dom\" {\n    pool /anothernetworkname/anotherhostname_80\n    }\n    default {\n         drop \n    }\n}\n}";
if (preg_match_all($re, $str, $matches)) {
    print_r($matches[0]);
}

Output:

Array
(
    [0] => networkname/hostname_80
    [1] => anothernetworkname/anotherhostname_80
)

Upvotes: 1

Noman
Noman

Reputation: 4116

Wiktor regex is right but it missing . after space \S, see preg_match_all Demo

/\bpool\h+\K\S.+$/m

Regex Explanation:

  1. \b assert position at a word boundary (^\w|\w$|\W\w|\w\W) pool matches the characters pool literally (case sensitive)
  2. \h+ matches any horizontal whitespace character (equal to [[:blank:]])
    • Quantifier — Matches between one and unlimited times, as many times as possible, giving back as needed (greedy)
  3. \K resets the starting point of the reported match. Any previously consumed characters are no longer included in the final match
  4. \S matches any non-whitespace character (equal to [^\r\n\t\f\v ])
  5. .+ matches any character (except for line terminators)
  6. Quantifier — Matches between one and unlimited times, as many times as possible, giving back as needed (greedy)
  7. $ asserts position at the end of a line

Global pattern flags

  1. m modifier: multi line. Causes ^ and $ to match the begin/end of each line (not only begin/end of string)

Upvotes: 2

Related Questions