user3400776
user3400776

Reputation: 11

Can't get my preg_match working

I just keep trying different combinations with preg_match or preg_match_all, but I'm plainly confused. Here's the code line that I use :

preg_match ("/(?<=(\[".$tag."\]))(.+)(?=(\[\/".$tag."\]))/s", $text, $matches);

(a look-behind and look-ahead to match the text within tags : [tag] (.+) [/tag]

The subject is a variable that contains text like this :

[title]Hi this is my title[/title]
[text]some text[/text]
[hidden]some hidden text[/hidden]
[text]again some more text[/text]
[end]end[/end]

Now I'm trying to display only the different parts of text within [text][/text] So I would like my echo to display :

some text
again some more text

However when I try to echo my $matches (array), the best I could get is :

some text[/text]
[hidden]some hidden text[/hidden]
[text]again some more text

It considers only the first and last tag. I've tried other combinations of parameters, but I just get errors regarding the offset, etc.

What should I do ? Thx!

Upvotes: 0

Views: 45

Answers (3)

Incorporate this simplified regex instead. /\['.$tag.'](.*?)\[\/'.$tag.']/

 <?php
 $tag = 'text';  //<--------- Pass the tag name (you can even add title , hidden )
    $str='[title]Hi this is my title[/title]
    [text]some text[/text]
    [hidden]some hidden text[/hidden]
    [text]again some more text[/text]
    [end]end[/end]';

    preg_match_all('/\['.$tag.'](.*?)\[\/'.$tag.']/', $str, $matches);
    print_r($matches[1]);

Demo

OUTPUT :

Array
(
    [0] => some text
    [1] => again some more text
)

enter image description here

Upvotes: 1

L3viathan
L3viathan

Reputation: 27283

This happens because of greedy quantifiers: By default, the + tries to take as much as it can. If you don't want that, add a ? after the quantifier to make it non-greedy:

preg_match ("/(?<=([".$tag."]))(.+?)(?=([/".$tag."]))/s", $text, $matches);

This way, the dot will try to match the smallest amount of characters possible.

As Shankar Damodaran pointed out, there's no need for lookaheads and lookbehinds here, so you might as well write:

preg_match ("/\[".$tag."](.+?)(\[\/".$tag."]/s", $text, $matches);

Upvotes: 1

Nambi
Nambi

Reputation: 12042

Use the preg_matchall

$input_lines='[title]Hi this is my title[/title]
[text]some text[/text]
[hidden]some hidden text[/hidden]
[text]again some more text[/text]
[end]end[/end]';

preg_match_all("/(?<=\[text\])(.*)(?=\[\/text\])/", $input_lines, $output_array);
print_r($output_array[0]);

output:

Array
(
    [0] => some text
    [1] => again some more text
)

Upvotes: 0

Related Questions