Question

Good day. I have a problem with a regular expression, I'm really stuck, the problem is that the field I'm trying to extract could be composed like:

NULL

Name#Size^Value#XXL^Quantity#3

Name#Size^Value#S^Name#Color^Value#Black^Quantity#2

The size will be always the first, color (optional) the second value, quantity the last. of course I would like to obtain those values to insert them in a database.

actually I have done this:

$txt='Name#Size^Value#S^Name#Color^Value#Black^Quantity#2';

  $re1='(Name#Size\\^Value#)';  
  $re2='((?:[a-z][a-z0-9_]*))'; 
  $re3='(\\^Name#Color\\^Value#)';  
  $re4='((?:[a-z][a-z0-9_]*))';
  $re5='(\\^Quantity#)';    
  $re6='(\\d+)';    

  if ($c=preg_match_all ("/".$re1.$re2.$re3.$re4.$re5.$re6."/is", $txt, $matches))
  {
      $word1=$matches[1][0];      
      $var1=$matches[2][0];
      $word2=$matches[3][0];
      $var2=$matches[4][0];
      $word3=$matches[5][0];
      $int1=$matches[6][0];
      print "<br> Size: $var1 <br> Color: $var2 <br> Quantity: $int1";
  }

but i'm not sure on how I can match the color as optional (and in that case take the quantity as second parameter.

Anyone could help me in this? It should be all wrong.. in that case, please point me in the good direction.

Was it helpful?

Solution 3

There is no need to do this with regex. You can solve it easily by splitting the string twice based on some rules.

Update: Here's the php code. Will work without a single regular expression, also for more complex combinations of these properties.

function split_string($string) {
  $properties = Array();
  $pairs = explode('^', $string);
  while ($pairs) {
    $first_pair = split('#', array_shift($pairs));
    if ($first_pair[0] == 'Name') {
      $second_pair = split('#', array_shift($pairs));
      $properties[$first_pair[1]] = $second_pair[1];
    } else {
      $properties[$first_pair[0]] = $first_pair[1];
    }
  }
  return $properties;
}

print_r(split_string("Name#Size^Value#S^Name#Color^Value#Black^Quantity#2"));
print_r(split_string("Name#Size^Value#XXL^Quantity#3")); 

Output:

Array
(
    [Size] => S
    [Color] => Black
    [Quantity] => 2
)
Array
(
    [Size] => XXL
    [Quantity] => 3
)

OTHER TIPS

Add ? in the end of the regexp of the color to match the color optionally

What about something drastically simpler like this:

(?:name#(\w+?)\^)?(?:value#(\w+?)\^)?(?:quantity#(\d+?))?

http://regex101.com/r/nN4yT3

Since your last bit (Quantity) doesn't follow the pattern, it ends up a bit goofy in the second capture group; in that respect, it might be easier to use named capture groups:

(?:name#(?<name>\w+?)\^)?(?:value#(?<value>\w+?)\^)?(?:quantity#(?<quantity>\d+?))?

Just need the optional quantifier (as others say).
But, it might be maintained better as -
(note - am not a php guru)

$re =
'/
     Name\#Size\^Value\#
     ( [a-z] [a-z0-9_]* )               # (1)
     \^Name\#Color\^Value\#
     ( [a-z] [a-z0-9_]* )?              # (2)
     \^Quantity\#
     ( \d+ )                            # (3)
/xi';

if ( preg_match_all ( $re, $txt, $matches ))
{
      $var1 = $matches[1][0];
      $var2 = $matches[2][0];
      $var3 = $matches[3][0];
      print "<br> Size: $var1 <br> Color: $var2 <br> Quantity: $var3";
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top