Adrian Modliszewski
Adrian Modliszewski

Reputation: 1124

PHP preg_match does not return all values as expected

I have strings like:

  1. postGeneratePasswordToken
  2. putUsers_VAL_Calculations_NUMBER_
  3. deleteUsers_VAL_Clients_ID_
  4. getDictionary_VAL_

the result i'm expecting is array (array per example above) with elements like below:

  1. post, Generate, Password, Token
  2. get, Users, _VAL_, Calculations, _NUMBER_
  3. delete, Users, _VAL_, Clients, _ID_
  4. get, Dictionary, _VAL_

below is my code:

$regex = '#(post|get|put|delete)(([A-Z][a-z]+)|(_[A-Z]{2,}_))+#';

$nameArray = preg_match_all($regex, $methodName, $matches);

and example output

array(5) {
  [0]=>
  array(1) {
    [0]=>
    string(33) "putUsers_VAL_Calculations_NUMBER_"
  }
  [1]=>
  array(1) {
    [0]=>
    string(3) "put"
  }
  [2]=>
  array(1) {
    [0]=>
    string(8) "_NUMBER_"
  }
  [3]=>
  array(1) {
    [0]=>
    string(12) "Calculations"
  }
  [4]=>
  array(1) {
    [0]=>
    string(8) "_NUMBER_"
  }
}

I know my regex works fine (checked with diffrent testers), but I have no Idea how to fix that, I've read documentation for preg_match, and It's not helpful since It's olny do return per group in regex. Any Idea how I can solve this problem?

Upvotes: 0

Views: 537

Answers (1)

zx81
zx81

Reputation: 41838

Any Idea how I can solve this problem?

Yes, you can use preg_split like this:

$result = preg_split('/(?<=[a-z])(?=[A-Z])|(?=_[A-Z]*_)|(?<=_)(?=[A-Z][a-z])/', $str);

The $result array has the strings you want.

The idea is that the regex used by preg_split does not match a string; rather, it matches a position in the string. This position is defined by lookarounds so it has zero characters.

This code produces the arrays you want (see the results at the bottom of the online demo):

<?php
$regex = "~(?<=[a-z])(?=[A-Z])|(?=_[A-Z]*_)|(?<=_)(?=[A-Z][a-z])~";
print_r(preg_split($regex,"postGeneratePasswordToken"));
print_r(preg_split($regex,"putUsers_VAL_Calculations_NUMBER_"));
print_r(preg_split($regex,"deleteUsers_VAL_Clients_ID_"));
print_r(preg_split($regex,"getDictionary_VAL_"));

Explain Regex

(?<=                     # look behind to see if there is:
  [a-z]                  #   any character of: 'a' to 'z'
)                        # end of look-behind
(?=                      # look ahead to see if there is:
  [A-Z]                  #   any character of: 'A' to 'Z'
)                        # end of look-ahead
|                        # OR
(?=                      # look ahead to see if there is:
  _                      #   '_'
  [A-Z]*                 #   any character of: 'A' to 'Z' (0 or more
                         #   times (matching the most amount
                         #   possible))
  _                      #   '_'
)                        # end of look-ahead
|                        # OR
(?<=                     # look behind to see if there is:
  _                      #   '_'
)                        # end of look-behind
(?=                      # look ahead to see if there is:
  [A-Z]                  #   any character of: 'A' to 'Z'
  [a-z]                  #   any character of: 'a' to 'z'
)                        # end of look-ahead

Upvotes: 1

Related Questions