Marcin Nabiałek
Marcin Nabiałek

Reputation: 111829

Get all occurences between characters to get same result

I'm looking inside string 3-431 a4-2 4-13 and want to find 3-431, a4-2 and 4-13. I use the following pattern:

/(.*-.* )*/gU

and I get the desired result without a problem: Online demo

The question is - how to achieve same result when I want to look inside string that start and ends with some other substrings for example [ and ].

If I modify subject to [3-431 a4-2 4-13 ] and regex to /\[(.*-.* )*\]/gU I'm getting only the last occurence: 4-13 and I'm not getting same results as in 1st example. Online demo

Why is that and how can I fix this?

Upvotes: 0

Views: 42

Answers (3)

Federico Piazza
Federico Piazza

Reputation: 30995

You don't need to use a regex you can use explode or split by space:

$str  = "3-431 a4-2 4-13";
$parts = explode(" ", $str);
echo $parts [0]; // 3-431
echo $parts [1]; // a4-2
echo $parts [2]; // 4-13

However, if you still want to use a regex, then you can use:

$re = "/(\\w+-\\w+)/"; 
$str = "3-431 a4-2 4-13"; 

preg_match_all($re, $str, $matches);

Regex demo

Btw, if your string is always separated by spaces, then you can also use this regex:

$re = "/(\\S+)/"; 
$str = "3-431 a4-2 4-13"; 

preg_match_all($re, $str, $matches);

Regex demo

On the other hand, if your string starts and ends with [ and ], as [3-431 a4-2 4-13 ]. The idea is to leverage the discard technique, you could use this regex:

[[\]](*SKIP)(*FAIL)|(\S+)

Working demo

And also, getting the same result using preg_split for above string:

$exploded = preg_split('[[\]\s]+', '[3-431 a4-2 4-13]', NULL, PREG_SPLIT_NO_EMPTY)

Upvotes: 1

Laurel
Laurel

Reputation: 6173

If you still wanted to do regex this will work:

(^|\])[^[]*\[([^[]*-[^[]* )*(*SKIP)(*FAIL)|(.*-.* )+

Basically, if the occurrence happens outside of [ and ] it will fail.


The reason that your were only getting one match is that the global modifier will only match another occurrence after the first match ends, which in your case was after the closing brace.

Upvotes: 0

Michele Carino
Michele Carino

Reputation: 1048

First of all, you should use .+ and not .* since + means at least once. Then your regex is:

/\[(\w+-\w+)*\s*\]/sgU

Upvotes: 0

Related Questions