Marko Korhonen
Marko Korhonen

Reputation: 3

PHP regex pattern for matching all

I have a-facebook-like mentioning feature in my app.

When creating posts or comments user can mention other users with @ sign. I use following jQuery plugin: http://podio.github.com/jquery-mentions-input/

Mentions are generated in the following format: @@[Marko Kurjonen:2] so "@@[User's name:user_id]

Currently I have following pattern (and code):

$pattern = "/@@\[(.*):(\d*)] /ims";

$matches = array();
preg_match_all($pattern, $input, $matches);
Zend_Debug::dump($matches);
$output = preg_replace($pattern, "<a href=\"". $this->view->baseUrl("user") ."/$2\" class=\"tooltip\">$1</a>", $input);

Problem is that it only does the first mention.

Example string:

$input = "Hello @@[Markku Pelkonen:7] and @@[Marko Kurjonen:2]"

Only first user gets converted by preg_replace.

br, Marko

Upvotes: 0

Views: 183

Answers (1)

nhahtdh
nhahtdh

Reputation: 56809

You can use this regex:

/@@\[([^:]*):(\d*)\]/

This regex assumes that the name doesn't contain : character.

The original regex has 2 problems:

  • The space at the end, just after ], causes the second mention to fail to match, since it is at the end of the input. (If you remove it, the greedy quantifier will gobble up the whole input string.)
  • The * in (.*) matches 0 or more instances greedily, which means it will match as many character as possible until the next token cannot match, where it will backtrack and try to match the next token. This is why the whole input string will be gobbled up if you remove the space, as mentioned above.

It is also possible to fix your regex a bit to make it work (apart from the solution I mentioned above):

/@@\[(.*?):(\d*)]/s

The m flag and i flag are useless here, so I remove them. You never use ^ or $ in your regex, so m flag is useless. The i flag is only useful if there are letter in the regex, which is not the case here.

I use *? quantifier here, which is the lazy version of match 0 or more. It will match as few character as possible just for the next token to be matched.

Upvotes: 2

Related Questions