Как вернуть только именованные группы с preg match или preg match all?
пример:
$string = "This is some text written on 2010-07-18.";
preg_match('|(?<date>dddd-dd-dd)|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.
8 ответов
Я не думаю, что вы можете сделать preg_*
сделать это, но вы можете сделать это с простой цикл. Но я не понимаю, почему эти элементы создают проблему.
preg_match
не имеет флага или опции, которая возвращает только именованные совпадения (пока). Поэтому то, чего вы хотите, прямо невозможно. Однако вы можете удалить все элементы с неподходящими ключами из массива matches, а затем вы получите то, что ищете:
$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):
этот подшаблон затем будет индексироваться в массиве matches его нормальное численное положение и также мимо имя.
для решения проблемы могут помочь следующие фрагменты кода:
1. отфильтруйте массив с помощью проверки is_string на ключе массива (для РНР5.6+)
$array_filtered = array_filter($array, "is_string", ARRAY_FILTER_USE_KEY);
2. foreach над элементами и unset, если ключ массива 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;
}
его простая функция PHP с именем dropNumericKeys()
. Его для последующей обработки массива совпадений после preg_match*()
выполнить с именем группы для сопоставления. Функции принимают $array
. Он выполняет итерацию массива и удаляет/отменяет все ключи с целочисленным типом, оставляя ключи со строковым типом нетронутыми. Наконец, функция возвращает массив с" now " только именованными ключами.
Примечание: функция предназначена для PHP нисходящей совместимости. Он работает на всех версиях. The 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]);
}
аналогично ответ что 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);
Я использую некоторые из введенных кодов, и это окончательный код работает на php 5.6+:
$re = '/\d+\r\n(?<start>[\d:]+),\d+\s--\>\s(?<end>[\d:]+),.*\r\nHOME.*\r\nGPS\((?<x>[\d\.]+),(?<y>[\d\.]+),(?<d>[\d\.]+)\)\sBAROMETER\:(?<h>[\d\.]+)/';
$str= file_get_contents($srtFile);
preg_match_all($re, $str, $matches, PREG_SET_ORDER, 0);
echo '<pre>';
$filtered=array_map(function ($d){
return $array_filtered = array_filter($d, "is_string", ARRAY_FILTER_USE_KEY);
},$matches);
var_dump($filtered);
Если вам интересно, что он делает, он читает данные о положении из файла str, который DJI дроны генерируют во время записи видео.
попробуйте это:
$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'];