greenbandit
greenbandit

Reputation: 2275

preg_match_all with spaces

have some headers like:

HTTP/1.1 100 Continue
HTTP/1.1 302 Found
HTTP/1.1 200 OK
HTTP/1.1 400 Not Found

so, I need to get 2 parts:

[200] => [OK]
[400] => [Not Found]

I need a way to use preg_match_all and get those values, but need to preserve the spaces at Not Found

have this code:

preg_match_all( '/([0-9]{3}) ([A-Za-z0-9+]*)/', $headers, $matches );

Works with 1-3 example headers.

Any ideas?

Upvotes: 1

Views: 2475

Answers (3)

Kaii
Kaii

Reputation: 20540

You can give your regex matches a name with (?P<name>), making your code more readable. also you can go with a much easier regex:

preg_match('#HTTP/1\.\d (?P<code>\d{3}) (?P<text>.*)#', $str, $matches);
echo $matches['code']; // 2100", same as $matches[1]
echo $matches['text']; // "Continue", same as $matches[2]

preg_match_all('#HTTP/1\.\d (?P<code>\d{3}) (?P<text>.*)#', $str, $matches, PREG_SET_ORDER);
echo $matches[0]['code']; // 100
echo $matches[0]['text']; // Continue
echo $matches[3]['code']; // 404
echo $matches[3]['text']; // Not Found

or even more simple, without regex using explode():

list(,$code,$text) = explode(" ", $str, 3); // works only on a single status line
echo $code; // 100
echo $text; // Continue

Upvotes: 3

Vyktor
Vyktor

Reputation: 20997

You are using almost good regexp but you're missing [ ] (space) from the character group definition, it should be: /([0-9]{3}) ([A-Za-z0-9 +]*)/.

Or rather use

  • \w instead of [A-Za-z]
  • \d instead of [0-9] and
  • \s instead of [ ]

So your patter would look like:

/(\d{3}) ([\w\d\s+]*)/

And make sure it won't match something it shouldn't

/HTTP\/1\.\d (\d{3}) ([\w\d\s+]+)/

So whole code would look like:

preg_match_all( '/HTTP\/1\.\d (\d{3}) ([\w\d\s+]+)/', $headers, $matches );

Here's an explanation for escape sequences.

Upvotes: 2

Cheery
Cheery

Reputation: 16214

For the single line and for the text in general

$str = "HTTP/1.1 100 Continue
HTTP/1.1 302 Found
HTTP/1.1 200 OK
HTTP/1.1 400 Not Found";

// for the values in the string, one on each line
preg_match_all('#(\d{3})\s+([\w\s]+)$#m', $str, $matches);
var_dump($matches);  // captures a new line symbol if exists

// for single value in the string
$str = "HTTP/1.1 400 Not Found";
preg_match('#(\d{3})\s+([\w\s]+)$#', $str, $matches);
var_dump($matches);

So, do you have each header on a new line or not?

Upvotes: 3

Related Questions