1

I'm struggling with what I imagine is quite a simple regex for a preg_match_all() call. I'm looking to mimic the Wikimedia style internal links system which will turn something like this [[link]] into a link.

I'm looking for a regex that will search a string for any example of [[foobar]] and return "foobar" to me. foobar should really be wild.

I've tried the following:

<?php
 $content = "Lorem ipsum dolor [[sit]] amet, consectetur adipiscing [[elit]].";
 $links = preg_match_all("[[*]]",$content,$matches);
 print_r($matches);
?>

I'm not getting much of anything. Any help would be appreciated.

4 Answers 4

4

* alone doesn't mean anything. It's a quantifier, it needs to be with something else. In this case, a dot . would do (means "anything"). Also, you can use lazy quantifiers instead of greedy ones to stop as soon as you encounter ]].
So...

$links = preg_match_all("/\[\[(.*?)]]/",$content,$matches);

Edit:
You have to escape the [ as they mark the beginning of character classes.

Sign up to request clarification or add additional context in comments.

10 Comments

A possessive quantifier with a negative character set would be more appropriate than lazy quantifiers.
Thanks for the extra info on ways to go about it.
Works well. +1 for the ?. But note @Jacks comment
@Jack fair enough. Though I think lazy quantifiers will make the regex more efficient than using a negative character class.
Lazy quantifiers do backtracking, so it shouldn't be used unless necessary.
|
2
preg_match_all("/\[\[([^\]]*?)\]\]/i",$content,$matches);

1 Comment

The ? and i are unnecessary.
1

You need to escape [ as \[ and then match the overall expression with the un-greedy flag U.

$content = "Lorem ipsum dolor [[sit]] amet, consectetur adipiscing [[elit]].";
$links = preg_match_all("/\[\[(.*)]]/U",$content,$matches);
print_r($matches);

Array(
    [0] => Array (
        [0] => [[sit]]
        [1] => [[elit]]
    )
    [1] => Array (
        [0] => sit
        [1] => elit
    )
)

EDIT: user ridgerunner pointed out that it's considered bad practice to use the /U modifier because it turns all matching quantifiers greedy, including ungreedy ones. The suggested matching code is (.*?) instead of what's posted above, and it produces the same equivalent answer.

$links = preg_match_all("/\[\[(.*?)]]/",$content,$matches);

5 Comments

Thanks for this, I can't accept for another 10 minutes, just counting down the time
Appreciate the courtesy. Cheers!
NEVER USE THE U FLAG! Best practice is to always use the ? ungreedy modifier on the quantifier itself right in the regex. There is never a case where the 'U' modifier is required and the only purpose it serves is to confuse. I rarely downvote an answer but until this is fixed, I am giving this answer my downvote. (Fix it and I'll remove my downvote)
Purpose of my answer was to show where the guy took the latest wrong turn, not to point out when he made a strategic blunder. Appreciate your explanation and respect your downvote, but I won't be threatened into changing an answer.
Did you know that the 'U' flag also turns ungreedy quantifiers to be greedy? For non-trivial regexes (having a mix of greedy and ungreedy quantifiers), the 'U' flag does nothing but make things very confusing (and bug prone). But don't take my word for it, go read Mastering Regular Expressions 3rd Edition.
1

Use the following pattern /\[\[(.*)\]\]/U :

$content = "Lorem ipsum dolor [[sit]] amet, consectetur adipiscing [[elit]].";
$links = preg_match_all("/\[\[(.*)\]\]/U",$content,$matches);
print_r($matches);

Explanation. The regex needs to start and end with a delimiter its the /. Square brackets [ have to be escaped in a regex like \[. The content between the brackets must be inside a capture group (.*). At last the ungreedy modifier is been used U to make sure that only the content between the nearest brackets will get captured. (remove to see its functionality)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.