9

I am trying to identify if a string has any words between double quotes using preg_match_all, however it's duplicating results and the first result has two sets of double quotes either side, where as the string being searched only has the one set.

Here is my code:

$str = 'Test start. "Test match this". Test end.';
$groups = array();
preg_match_all('/"([^"]+)"/', $str, $groups);
var_dump($groups);

And the var dump produces:

array(2) {
    [0]=>
    array(1) {
        [0]=>
        string(17) ""Test match this""
    }
    [1]=>
    array(1) {
        [0]=>
        string(15) "Test match this"
    }
}

As you can see the first array is wrong, why is preg_match_all returning this?

Styphon
  • 10,304
  • 9
  • 52
  • 86
  • Leave out the brackets, or add some brackets, read the manual and you'll work it out – Elias Van Ootegem Oct 28 '14 at 11:01
  • Please define *wrong*. How is that not matching up your expectations that http://php.net/preg_match_all gives? – hakre Oct 28 '14 at 11:07
  • 1
    As you don't define wrong, it could be also that you're confusing the output of `var_dump` here? – hakre Oct 28 '14 at 11:14
  • Yes, I'm confusing `var_dump`. I didn't realise that `preg_match_all` recorded with and without the capture, and that it was `var_dump` adding quotes around the strings. The two lots of double quotes is what I thought was *wrong*. – Styphon Oct 28 '14 at 11:18

4 Answers4

11

It returns 2 elements because:

Element 0 captures the whole matched string

Elements 1..N capture dedicated matches.

PS: another way of expressing the same could be

(?<=")[^"]+(?=")

which would capture exactly the same but in that case you don't need additional capturing group.

Demo: http://regex101.com/r/lF3kP7/1

zerkms
  • 249,484
  • 69
  • 436
  • 539
  • This doesn't produce the results I expect, it includes the end string - https://eval.in/210849 – Styphon Oct 28 '14 at 11:12
  • @Styphon: hint: `(?=")` – zerkms Oct 28 '14 at 11:14
  • @Avinash Raj: `var_dump` encloses all string literals in double quotes. It's not what a question is about though. – zerkms Oct 28 '14 at 11:15
  • @Avinash Raj: that's right, and `print_r` does not solve the "issue". It's about understanding how `preg_match_all` works, not about `print_r` vs `var_dump` – zerkms Oct 28 '14 at 11:17
  • @Avinash Raj: that's not what OP asked in the question though. I'm sorry, but I cannot read OP's minds. – zerkms Oct 28 '14 at 11:19
  • @Avinash Raj: for me it looks like OP was confused about 2 items instead of one. I could not realize someone would be confused that a string literal is delimited in quotes, it's just... unbelievable :-S – zerkms Oct 28 '14 at 11:20
  • I was asking why there was two results, one with quotes and one without, but that was me being confused by var_dump and then not understanding how preg_match_all worked. – Styphon Oct 28 '14 at 11:21
  • 1
    @Styphon: sorry then. I'm used to thinking that an OP with 100+ answers checks the documentation first. I was so wrong :-D – zerkms Oct 28 '14 at 11:23
  • I had checked the documentation, I just misunderstood it. It's easy enough to do if you're not used to using something. – Styphon Oct 28 '14 at 11:33
  • 1
    @Styphon: Fair enough (I would try to use the function I do not understand on multiple inputs though before I ask a question. `var_dump('foo')` would demonstrate its behaviour) – zerkms Oct 28 '14 at 11:35
  • Point taken. I'll make sure to do that in future. – Styphon Oct 28 '14 at 11:39
8

Hi if your are using print_r instead of vardump you will see the differences in a better way.

Array
(
    [0] => Array
        (
            [0] => "Test match this"
        )

    [1] => Array
        (
            [0] => Test match this
        )

)

The first contains whole string and the second is your match.

2

Remove the parenthesis. you can write the pattern as '/"[^"]+"/'

Shubham joshi
  • 91
  • 1
  • 4
2

This is because you're using group matching. take the parentheses out of your pattern and you'll get one array back. Something like:

preg_match_all('/\"[^"]+\"/', $str, $groups);