Good afternoon, good people. In regular expressions recently, one line is tormenting ... well, it does not give way either.

preg_match("/^([A-z_0-9\$\s\-]+)(|\-([a-z24]+))$/i", $urlprop['func'], $urllogin22); 

This is the regular line itself.

In urlprop, the url string is stored, in which there can be 2 positions:

  • Product Name
  • TitleProduct-Option

The problem lies in the fact that the name of the product may contain a dash "-" and the regular schedule no longer splits the URL into "the name of the goods" and "Option."

Tell me what is wrong in my expression and how could this be corrected?

  • So it is for the "name of the goods-option" does not work. - Yaroslav Molchan
  • She works on finding the name of the goods even if there is a dash in it. And I would need to be able to determine also the option, without disassembling the title of the Goods into parts through the dash - Petr Likrov
  • @ PetrLikrov and the названиеТовара goods always has this format? That is, the name of the product is always written on the camel case? If you can, give an example of a real name. - Edward
  • No =) just seems so beautiful and easy to read in my opinion. url: site_ru / catalog / verbljuzhiishrift-vzgrev-option - Peter Likrov
  • @ PetrLikrov posted a response - Edward

4 answers 4

I think initially the problem is not in regular expression, but in logic, I will give an example for clarity: There are such URLs:

 Товар-Опция Товар-товар-Опция Товар-товар-товар-Опция 

And with the help of Look ahead we divide the string by the last character - :

 preg_match("/^(.*)(?=-)[-*](.*)$/i", $urlprop['func'], $urllogin22); var_dump($urllogin22); array(3) { [0]=> string(12) "Товар-Опция" [1]=> string(5) "Товар" [2]=> string(6) "Опция" } 

In all 3 options, it will work as it should, but if there is a product that is without a category:

 Товар-товар 

And a product with a category from the first example:

 Товар-Опция 

For regulars this is the same, you need to change the url structure to understand exactly where the product is where the option is.

    Thanks for the most working answer.

     $opt = str_replace('-','',substr($urlprop['func'], strrpos($urlprop['func'], '-'))); $options = array('option1','option2','option3','option4'); if(in_array($opt,$options)){ // если есть опция }else{ // если последнее слово после тире не подходит ни под одну из опций } 

    It turned out to be easier to solve this problem without a regular expression =)

      If the string has the format " Item-Item-Option ", then the part " Item-Item Name " will be saved in the item name , and in the Option option .

      If the option is not specified, then the name of the item will contain the string " Name of the item "

       $str = 'НазваниеТовара-Опция'; $option = ''; preg_match_all('~\w+-?\w+~u', $str, $a); count($a[0]) > 1 ? list($name, $option) = $a[0] : $name = $a[0]; var_dump($name, $option); 

      UPD: If the options are known in advance, then you can do without regular expressions:

       $url = 'НазваниеТовара-option1'; $temp = explode('-', $url); $option = array_pop($temp); $options = ['option1', 'option2', 'option3', 'option4']; if (($k = array_search($option, $options)) !== false) { echo 'Товар: '. join($temp) . '<br>Опции: ' . $options[$k]; } 
      • Again, if there is a "Name of the Goods-Option" (the name without a dash) - it gives an error. - Peter Likrov
      • @ PetrLikrov what mistake? Error text copy here, please, and I will correct my answer. - Edward
      • Notice: Undefined offset: 1 in /var/www/html/framework/list.php on line 6 string (22) "nazvaniebeztire-option1" NULL - Peter Lycrow
      • one
        @ PetrLikrov corrected the answer. There will be no errors, but there will also be no division into Name_Option with this format of the incoming line. You need to add a separator, and then navigate through this separator. - Edward
      • Thank you very much for the inclusion. The most working variant without regulars in general - from Nik, sounded in the comments to one of the answers above. - Peter Likrov

      You can use preg_split with Negative Lookahead, which will find the last hyphen in the string

       list($name, $option) = preg_split('/\-(?!.*\-)/', 'Название-товара-Опция'); echo $name.'<>',$option; // Название-товара<>Опция 
      • And what if in the reference the position "Title of the Product " has a dash, it turns out he will break the "Title of the Product " into a semi-title and supposedly option - Peter Lykrov
      • one
        @PetrLikrov, how can we then understand what is the option and what is the name of the product. If the option may not be, and the title may have a dash, then it cannot be unambiguously understood if the option does not have any distinctive properties. - Nik
      • And if we admit the names of the options, i.e. there are 10 of them, and they are predetermined ... will it change anything? - Peter Likrov
      • if the list is known - yes - splash58
      • one
        @ PetrLikrov in this case there are no regulars needed at all. We can get the option like this: $opt = substr($urllogin, strrpos($urllogin, '-'));if(!in_array($opt, $option)) $opt = ''; . In case there is no option, it will be equal to an empty string. - Nik