0

I want to parse a string like a shortcode that can have or not variables, and put these variables in a array. The given text is:

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur pulvinar erat quis aliquet pulvinar. Vivamus egestas eros at augue dictum, {mycode var1=foo|var2=zoo|var3=123a|othervarname=digit} a ultrices nisl ullamcorper. Nullam condimentum orci eros, non ornare magna accumsan in.

My regex now is:

{mycode\s?(?:(?:(\w+)\={1}(\w+)))*\|?\}*

Result is:

Array
(
    [0] => Array
        (
            [0] => {mycode var1=foo|
        )

    [1] => Array
        (
            [0] => var1
        )

    [2] => Array
        (
            [0] => foo
        )

)

I want this type of array:

Array
(
    [0] => Array
        (
            [0] => var1
            [1] => foo
        )

    [1] => Array
        (
            [0] => var2
            [1] => zoo
        )

    [2] => Array
        (
            [0] => var3
            [1] => 123a
        )

    [3] => Array
        (
            [0] => othervarname
            [1] => digit
        )

)

Or:

Array
(
    [0] => Array
        (
            [var1] => foo
        )

    [1] => Array
        (
            [var2] => zoo
        )

    [2] => Array
        (
            [var3] => 123a
        )

    [3] => Array
        (
            [othervarname] => digit
        )

)

Thank you very much. Serafino

4
  • Where are the huhu and ih coming from? And to have only one occurrence of a character you don't need {1} so {mycode\s?(?:(?:(\w+)\=(\w+)))*\|?\}* is the same regex as yours but simplified a bit Commented Mar 11, 2014 at 8:41
  • huhu an ih? sorry I've cleaned the code @MisterJ Commented Mar 11, 2014 at 8:46
  • you can see now the result Commented Mar 11, 2014 at 8:51
  • @SerafinoBilotta could there be several of these codes in one input ? Something like test {mycode var1=foo} and another code {mycode var2=foo2} ? Commented Mar 12, 2014 at 11:00

2 Answers 2

1

I suggest to apply two regexps: 1) content of {mycode...}; 2) content of each variable pair in {mycode...}. Somehow like this:

$a_result = 0;
if (preg_match('/\{mycode\s+([^{}]+)\}/', $text, $arr) &&
    preg_match_all('/([A-Za-z\d]+)[=]([A-Za-z\d]+)/', $arr[1], $arr, PREG_SET_ORDER))
    $a_result = array_map(function ($v) { return array($v[1], $v[2]); }, $arr);

Demo

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

1 Comment

this is what I do in my working script, I want to know if is it possible to do it in only one regex?
1

If I understand what you are wanting, I think what you are wanting to do is entirely possible.

Here's a demo that returns three variations of your matches and stores them in a variable called $matches.

  1. The first one is what it actually captured.
  2. The second one is what we will use to make your first desired array.
  3. The last two I combine as one match to make the array you will use to build out your second desired array.

Here's the code:

$string = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur pulvinar erat quis aliquet pulvinar. Vivamus egestas eros at augue dictum, {mycode var1=foo|var2=zoo|var3=123a|othervarname=digit} a ultrices nisl ullamcorper. Nullam condimentum orci eros, non ornare magna accumsan in.';

// TRY AND PULL OUT THE MATCHES
preg_match_all('/(?:(?:\{mycode |\|))(([A-Z0-9]+)=([^|}\s]+)+)/i', $string, $matches);

// PRINT IT OUT TO SEE WHAT IT FOUND
print "<pre><font color='orange'>"; print_r($matches); print "</font></pre>";


// NOW, YOU CAN BUILD EITHER TYPE OF ARRAY
// TO GET THE FIRST KIND OF ARRAY YOU WANT, TRY THIS:
$final_array = array();
foreach ($matches[1] AS $pair) {
    $final_array[] = explode('=', $pair);
}   

print "<pre><font color=red>"; print_r($final_array); print "</font></pre>";



// TO GET THE SECOND TYPE OF ARRAY, YOU CAN TRY THIS:
$final_array = array();
$combine = array_combine($matches[2], $matches[3]);
foreach ($combine AS $key => $val) {
        $final_array[] = array($key => $val);   
}

print "<pre><font color=blue>"; print_r($final_array); print "</font></pre>";

Here is a demo

3 Comments

your code works well, but I want to know if there is a way to do that only with the regex, without manipulating the array with php :D
I don't believe you can change how PHP writes to the variable $matches. It just stores what it finds as it finds them. You can control how it's stored to a certain extent with your expression using parenthesis, but I'm not entirely sure how you'd go beyond what I have. I know you cannot generate the second type of array, since the keys will always be numbers. As for the first one, I'm not positive on. It may be possible, but what I think you're trying to do there would be a preg_match within a preg_match and I don't know how that's possible to achieve.
preg_replace has preg_replace_callback in which you can manipulate the data to do something like what you are wanting. But preg_match does not have anything like that.

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.