0

I'm having troubles extracting several strings between tags from a variable, in order to echo them inside a span individually.
Thing is, the tags in question are determined by a variable, here is what it looks like :

<?php
    $string = "[en_UK]english1[/en_UK][en_UK]english2[/en_UK][fr_FR]francais1[/fr_FR][fr_FR]francais2[/fr_FR][fr_FR]francais3[/fr_FR]";
    $lang = "en_UK";

    preg_match("/(.[$lang]), (.[\/$lang])/", $string, $outputs_list);

    foreach ($outputs_list as $output) {
        echo "<span>".$output."/span>";
    }

    // in this exemple I want to output :
    // <span>english1</span>
    // <span>english2</span>
?>

It's my first time using preg_match and after trying so many differents things I'm kinda lost right now.
Basically I want to extract every strings contained between the tags [$lang] and [/$lang] (in my exemple $lang = "en_UK" but it will be determined by the user's cookies.

I'd like some help figuring this out if possible,

Thanks

2
  • Thanks for your answer, yes I kinda got lost in my attempts. How ever do you think the $lang will output "en_UK" in your code ? Or do I need to escape it like preg_match_all("/\[".$lang."\](.+?)\[\/".$lang."\]/", $string, $outputs_list);? Thanks ! Commented Nov 26, 2016 at 20:14
  • Either or will work since you are in double quotes. I've moved that down as an answer. Commented Nov 26, 2016 at 20:15

2 Answers 2

1

[] in a regular expression makes a character class. I'm not sure what you're trying to do with the .s and , either. Your regex currently says:

Any single character, an e, n, _, U, or K, a , and space, and again any single character, an e, n, _, U, K, but this time also allowing /.

Regex demo: https://regex101.com/r/8pmy89/2

I also believe you were grouping the wrong value. The () go around what you want to capture, know as a capture group.

I think the regex you want is:

\[$lang\](.+?)\[\/$lang\]

Regex demo: https://regex101.com/r/8pmy89/3

PHP Usage:

$string = "[en_UK]english1[/en_UK][en_UK]english2[/en_UK][fr_FR]francais1[/fr_FR][fr_FR]francais2[/fr_FR][fr_FR]francais3[/fr_FR]";
$lang = "en_UK";
preg_match_all("/\[$lang\](.+?)\[\/$lang\]/", $string, $outputs_list);
foreach ($outputs_list[1] as $output) {
    echo "<span>".$output."/span>";
}

PHP demo: https://eval.in/686086

Preg_match vs. preg_match_all

Preg_match only returns the first match(es) of a regex. Preg_match_all returns all matches of the regex. The 0 index has what the full regex matched. All subsequent indexes are each capture groups, e.g. 1 is the first capture group.

Simple Demo: https://eval.in/686116

$string = '12345';
preg_match('/(\d)/', $string, $match);
print_r($match);
preg_match_all('/(\d)/', $string, $match);
print_r($match);

Output:

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

^ is preg_match, below is the preg_match_all

Array
(
    [0] => Array
        (
            [0] => 1
            [1] => 2
            [2] => 3
            [3] => 4
            [4] => 5
        )

    [1] => Array
        (
            [0] => 1
            [1] => 2
            [2] => 3
            [3] => 4
            [4] => 5
        )

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

3 Comments

Thank you, this is now working. However I don't understand what the [1] after $outputs_list stand for ? And one final question that I didn't add to my original question to simplify things : if instead of $lang I have $user['lang'] Do I need to escape it in a particular way or is it gonna work if I leave it like this ?
And thanks for detailling your answer as much, indeed my capture group was basically null in my attempt.
Preg_match_all makes multiple matches, the 1 index is the first capture group
1

I made little late to post this answer. @chris already answered your question, so i made the solution broad which might help other users who may have different requirements.

<?php
$string = "[en_UK]english1[/en_UK][en_UK]english2[/en_UK][fr_FR]francais1[/fr_FR][fr_FR]francais2[/fr_FR][fr_FR]francais3[/fr_FR]";
$lang = "en_UK";
echo "User Language -";
preg_match_all("/\[$lang\](.+?)\[\/$lang\]/", $string, $outputs_list);
foreach ($outputs_list[1] as $output) {
    echo "<span>".$output.",</span>";
}
echo "<br/>All languages - ";
//if all lang
preg_match_all("/[a-zA-Z0-9]{3,}/", $string, $outputs_list);
foreach ($outputs_list[0] as $output) {
    echo "<span>".$output.",</span>";
}
echo "<br/>Type of lang - ";
//for showing all type of lang
preg_match_all("/(\[[a-zA-Z_]+\])*/", $string, $outputs_list);
foreach ($outputs_list[1] as $output) {
    echo "<span>".$output."</span>";
}
?>

OUTPUT

User Language -english1,english2,

All languages - english1,english2,francais1,francais2,francais3,

Type of lang - [en_UK][en_UK][fr_FR][fr_FR][fr_FR]

1 Comment

@chris85, Happy to help, and welcome to Stack Overflow. If this answer or any other one solved your issue, please mark it as accepted. It will be helpful to other users

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.