Как вернуть только имена групп с preg_match или preg_match_all?

Пример:

$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); 

Возвращает:

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

Но я хочу, чтобы это было:

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

В объекте PDO PHP есть опция, которая фильтрует результаты из базы данных, удаляя эти повторяющиеся пронумерованные значения: PDO::FETCH_ASSOC . Но я еще не видел подобного модификатора для функций PCRE в PHP.

Я не думаю, что вы можете сделать preg_* , но вы можете сделать это с помощью простого цикла. Но я не понимаю, почему эти элементы создают проблему.

preg_match не имеет ни одного флага или опции, что он возвращает только имена совпадений (пока). Так что вы не хотите напрямую. Однако вы можете удалить все элементы с неподходящими ключами из массива совпадений, а затем получить то, что вы ищете:

 $matches = array_intersect_key($matches, array_flip(array('name', 'likes'))); 

демонстрация

Как вернуть только имена групп с preg_match или preg_match_all?

Это в настоящее время (PHP7) невозможно. Вы всегда получите массив смешанного типа, содержащий числовые и именованные ключи.

Давайте процитируем руководство по PHP ( http://php.net/manual/en/regexp.reference.subpatterns.php ):

Затем этот подшаблон будет индексироваться в массиве совпадений по его обычной числовой позиции, а также по имени.


Чтобы решить эту проблему, следующие фрагменты кода могут помочь:

1. фильтруйте массив с помощью проверки is_string на ключе массива (для PHP5.6 +)

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

2. Зафиксировать элементы и отключить, если ключ массива is_int () (все версии PHP)

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

Его простая функция PHP с именем dropNumericKeys() . Его для последующей обработки массива совпадений после запуска preg_match*() с использованием названных групп для сопоставления. Функции принимают $array . Он выполняет итерацию массива и удаляет / отключает все ключи с целым типом, оставляя ключи со строковым типом нетронутыми. Наконец, функция возвращает массив с «теперь» только с именованными ключами.

Примечание. Функция предназначена для понижающей совместимости PHP. Он работает на всех версиях. Решение array_filter зависит от константы ARRAY_FILTER_USE_KEY , доступной только на PHP5.6 +. См. http://php.net/manual/de/array.constants.php#constant.array-filter-use-key

Также возможно отменить все числовые индексы перед возвратом:

 foreach (range(0, floor(count($arr_result) / 2)) as $index) { unset($arr_result[$index]); } с foreach (range(0, floor(count($arr_result) / 2)) as $index) { unset($arr_result[$index]); } 

Подобно тому, что hakre опубликовал выше, я использую этот фрагмент, чтобы получить только именованные параметры:

 $subject = "This is some text written on 2010-07-18."; $pattern = '|(?<date>\d\d\d\d-\d\d-\d\d)|i'; preg_match_all($pattern, $subject, $matches, PREG_SET_ORDER); echo '<pre>Before Diff: ', print_r($matches, 1), '</pre>'; $matches = array_diff_key($matches[0], range(0, count($matches[0]))); echo '<pre>After Diff: ', print_r($matches, 1), '</pre>'; 

… который производит это:

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

Я прочитал в вашем сообщении, что это возможные перегрузки будущей памяти и т. Д. В этом случае, почему бы не решить проблему с unset () :

 $string = "This is some text written on 2010-07-18."; preg_match('|(?<date>\d{4}-\d{2}-\d{2})|i', $string, $arr_result); $date = array("date" => $arr_result['date']); unset($arr_result, $string);//delete array and string preg_match origen print_r($date); //or create a new: // $arr_result = $date; //print_r($arr_result); 

Попробуй это:

 $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); echo $arr_result['date'];