Search code examples
phpregexsmarty

Smarty/PHP Regex replace


I have the next string:

countries_united_states_ohio

sometimes it can be countries_spain_madrid

How can I remove the word Countries and have the next output:
United States, Ohio
or
Spain, Madrid

I'm using Smarty and I tried something like this:

{$string|replace:"_":", "|capitalize}

The problem is that it returns United,States(as expected) and I guess I could remove the word 'countries' using substr.

Anyone has any idea?

Thank you!


Solution

  • I think I found a way.
    You will need a list of all countries in the world. Example: https://www.countries-ofthe-world.com/all-countries.html

    The code will look at each part of the string and see if it's a "country word" if true:
    It will make sure it has not already grabbed that word (see all "uinited" countries).
    If it is not already in the country array then add it there.

    Now I can just implode the country.

    State/city is what is left of I remove country and _.

    $Ucountries = ["Uganda",
       "Ukraine",
       "United Arab Emirates (UAE)",
       "United Kingdom (UK)",
       "United States of America (USA)",
       "Uruguay",
       "Uzbekistan"];
    
    $Mcountries = ["Macedonia (FYROM)",
       "Madagascar",
       "Malawi",
       "Malaysia",
       "Maldives",
       "Mali",
       "Malta",
       "Marshall Islands",
       "Mauritania",
       "Mauritius",
       "Mexico",
       "Micronesia",
       "Moldova",
       "Monaco",
       "Mongolia",
       "Montenegro",
       "Morocco",
       "Mozambique",
       "Myanmar (Burma)"];
    
    $str = "countries_mexico_mexico_city";
    //$str = "countries_united_states_ohio";
    $str = str_replace("countries_", "", $str);
    
    // Copy array needed to $CountryList
    $CountryList = ${strtoupper(substr($str,0,1)). "countries"}; 
    
    $countryarr = array();
    $arr = explode("_", $str);
    
    Foreach($arr as $val){
        Foreach($CountryList as $item){
            If(stripos($item, $val) !== false){
                If(!in_array($val, $countryarr)){
                    $countryarr[] = $val;
                }
            }
        }
    }
    
    $country = implode(" ", $countryarr);
    $state_city = preg_replace("/" . implode("_",$countryarr) . "/", "", $str,1);
    $state_city = trim(str_replace("_", " ", $state_city));
    
    Echo $country . "\n" . $state_city;
    

    https://3v4l.org/POMPT

    Edit; thought of a way when I was brushing my teeth.
    Since the countryarr will only have Mexico I can with preg_replace replace only once.
    Also I had to change the replace pattern to a implode of countryarr.
    Now what is left is a state/city with a underscore first and one or more words separated with underscore.
    So replace underscore with space and trim the string.

    EDIT2; Now that I have had some sleep I thought that the array to match against countries will be very large.
    So I made a change.
    Each first letter of country is a new array, and the code will only loop in the countries with the same first letter.