Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to return only named groups with preg_match or preg_match_all?

Example:

$string = "This is some text written on 2010-07-18.";
preg_match('|(?<date>\d\d\d\d-\d\d-\d\d)|i', $string, $arr_result);
print_r($arr_result);

Returns:

Array
(
    [0] => 2010-07-18
    [date] => 2010-07-18
    [1] => 2010-07-18
)

But I want it to be:

Array
(
    [date] => 2010-07-18
)

In PHP's PDO object there is an option that is filtering results from database by removing these duplicate numbered values : PDO::FETCH_ASSOC. But I haven't seen similar modifier for the PCRE functions in PHP yet.

like image 573
rsk82 Avatar asked Jul 18 '10 14:07

rsk82


People also ask

What is the use of Preg_match () method?

The preg_match() function returns whether a match was found in a string.

What value is return by Preg_match?

Return Values ¶ preg_match() returns 1 if the pattern matches given subject , 0 if it does not, or false on failure. This function may return Boolean false , but may also return a non-Boolean value which evaluates to false .

Which of the following call to Preg_match will return true?

The preg_match() function returns true if pattern matches otherwise, it returns false.

What is the purpose of Preg_match () regular expression in PHP?

The preg_match() function will tell you whether a string contains matches of a pattern.


2 Answers

How to return only named groups with preg_match or preg_match_all?

This is currently (PHP7) not possible. You will always get a mixed type array, containing numeric and named keys.

Lets quote the PHP manual (http://php.net/manual/en/regexp.reference.subpatterns.php):

This subpattern will then be indexed in the matches array by its normal numeric position and also by name.


To solve the problem the following code snippets might help:

1. filter the array by using an is_string check on the array key (for PHP5.6+)

$array_filtered = array_filter($array, "is_string", ARRAY_FILTER_USE_KEY);

2. foreach over the elements and unset if array key is_int() (all PHP versions)

/**
 * @param array $array
 * @return array
 */
function dropNumericKeys(array $array)
{
    foreach ($array as $key => $value) {
        if (is_int($key)) {
            unset($array[$key]);
        }
    }
    return $array;
}

Its a simple PHP function named dropNumericKeys(). Its for the post-processing of an matches array after a preg_match*() run using named groups for matching. The functions accepts an $array. It iterates the array and removes/unsets all keys with integer type, leaving keys with string type untouched. Finally, the function returns the array with "now" only named keys.

Note: The function is for PHP downward compatiblity. It works on all versions. The array_filter solution relies on the constant ARRAY_FILTER_USE_KEY, which is only available on PHP5.6+. See http://php.net/manual/de/array.constants.php#constant.array-filter-use-key

like image 125
Jens A. Koch Avatar answered Sep 19 '22 22:09

Jens A. Koch


preg_match does not have any flag or option that it only returns named matches (yet). So what you want is not directly possible. However you can remove all items with non-fitting keys from your matches array and then you get what you're looking for:

$matches = array_intersect_key($matches, array_flip(array('name', 'likes')));
like image 36
hakre Avatar answered Sep 16 '22 22:09

hakre