Why is preg_match_all returning two matches?
Asked Answered
S

4

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?

Spa answered 28/10, 2014 at 10:57 Comment(4)
Leave out the brackets, or add some brackets, read the manual and you'll work it outFossilize
Please define wrong. How is that not matching up your expectations that php.net/preg_match_all gives?Conservative
As you don't define wrong, it could be also that you're confusing the output of var_dump here?Conservative
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.Spa
P
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.

Photocurrent answered 28/10, 2014 at 11:4 Comment(1)
Right, didn't realise that preg_match_all returned both, thank you.Spa
S
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

Stud answered 28/10, 2014 at 11:0 Comment(11)
This doesn't produce the results I expect, it includes the end string - eval.in/210849Spa
@Styphon: hint: (?=")Stud
@Avinash Raj: var_dump encloses all string literals in double quotes. It's not what a question is about though.Stud
@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_dumpStud
@Avinash Raj: that's not what OP asked in the question though. I'm sorry, but I cannot read OP's minds.Stud
@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 :-SStud
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.Spa
@Styphon: sorry then. I'm used to thinking that an OP with 100+ answers checks the documentation first. I was so wrong :-DStud
I had checked the documentation, I just misunderstood it. It's easy enough to do if you're not used to using something.Spa
@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)Stud
Point taken. I'll make sure to do that in future.Spa
P
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.

Photocurrent answered 28/10, 2014 at 11:4 Comment(1)
Right, didn't realise that preg_match_all returned both, thank you.Spa
D
2

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

Demarcate answered 10/4, 2019 at 21:29 Comment(0)
D
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);
Dessert answered 30/7, 2020 at 8:47 Comment(1)
Why are you escaping the quotes?Toluidine

© 2022 - 2024 — McMap. All rights reserved.