从捕获的组中提取值

时间:2018-05-03 22:12:41

标签: php regex

我有RegEx

^(?:([0-9]+) X,)?(?: )?(?:([0-9]+) Y,)?(?: Z)?$

我所做的是检查以下模式:

66 X, 55 Y, Z
66 X, 55 Y,
66 X, Z
55 Y, Z
66 X,
55 Y,

Group 166 X,

Group 255 Y,

我想要做的是拉取值并使用以下内容进行检查:

if (isset($group_1)) {
    echo $group_1;
} else {
    echo 'null';
}
echo ' - ';
if (isset($group_2)) {
    echo $group_2;
} else {
    echo 'null';
}

根据模式

获得如下结果
66 - 55
66 - 55
66 - null
null - 55
66 - null
null - 55

如何使用PHP

执行此操作

3 个答案:

答案 0 :(得分:2)

使用preg_match(_all)?函数,您有一个数组作为返回值。您可以这样使用该数组:

// An unnecessary non-capturing group removed 
$re = '/^(?:([0-9]+) X,)? ?(?:([0-9]+) Y,)?(?: Z)?$/m';
// Preparing feeds
$str = <<<_
66 X, 55 Y, Z
66 X, 55 Y,
66 X, Z
55 Y, Z
66 X,
55 Y,
\n
_;

// `PREG_SET_ORDER` flag is important
preg_match_all($re, $str, $matches, PREG_SET_ORDER);

// Iterate over matches
foreach ($matches as $match) {
    // Remove first value off array (whole match)
    unset($match[0]);
    // Add `null` to existing empty value or the one that is not captured
    foreach (['null', 'null'] as $key => $value) {
        if (!isset($match[$key + 1]) || $match[$key + 1] === '')
            $match[$key + 1] = $value;
    }
    // Implode remaining values
    echo implode(" - ", $match), PHP_EOL;
}

输出(Live demo):

66 - 55
66 - 55
66 - null
null - 55
66 - null
null - 55
null - null

答案 1 :(得分:1)

我宁愿用普通的数组函数来做。解释是作为对以下代码的评论而给出的

<?php
$str="66 X, 55 Y, Z
66 X, 55 Y,
66 X, Z
55 Y, Z
66 X,
55 Y,";

//remove all Zs as it is not needed here
$str=str_replace("Z","",$str);
//split the string with new line 
$arr=explode("\n",$str);
$final=array();

foreach($arr as $val){
    //remove white spaced entry 
    $inner_arr=array_filter(array_map('trim',(explode(",",$val))));
    //if it has only one entry fill the array with either x on 1st or y on the last,remember it is always array of size 2, we have already removed whitespace and z entry
    if(count($inner_arr)==1){
        //fill with x of y  
        //if 1st entry is not X , fill 1st entry with X 
        if(strpos($inner_arr[0],'X')===false){
            array_unshift($inner_arr,'NULL X');
        }
        //otherwise fill last entry with Y
        else{
           array_push($inner_arr,'NULL Y');   
        }

    }
    //print_r($inner_arr);
    //replace x and y with blank value
    array_push($final,str_replace(array('X','Y'),'',(implode("-",$inner_arr))));
}
//join them back with new line
$final_str=implode("\n",$final);
echo $final_str;
?>

输出

66 -55 
66 -55 
66 -NULL 
NULL -55 
66 -NULL 
NULL -55 

工作小提琴http://phpfiddle.org/main/code/8bk5-k3u1

答案 2 :(得分:1)

由于您的任务似乎是提取而非验证,因此您无需检查开始或结束锚点以及Z组件。

由于模式允许所有目标子串都是可选的,因此您需要检查给定元素是否存在且不是空字符串。这是因为当preg_match()找到Y但没有X时,它会在[1]中创建一个空元素。或者,如果preg_match()找到X,没有Y,不会生成空的[2]元素。

您的输入数据有点含糊不清;我假设你正在处理单独的字符串,但总体技术仍然是相同的。

代码:(Demo

$inputs = [
    '66 X, 55 Y, Z',
    '66 X, 55 Y,',
    '66 X, Z',
    '55 Y, Z',
    '66 X,',
    '55 Y',
    '44 Z'
];
foreach ($inputs as $input) {
    if (preg_match('~(?:(\d+) X)?,? ?(?:(\d+) Y)?~', $input, $out)) {
        echo (isset($out[1]) && $out[1] !== '') ? $out[1] : 'null';  // if zero is a project-impossibility, only use !empty()
        echo " - ";
        echo isset($out[2]) ? $out[2] : 'null';
        echo "\t\t\t(from: $input)\n";
    }
}

输出:

66 - 55             (from: 66 X, 55 Y, Z)
66 - 55             (from: 66 X, 55 Y,)
66 - null           (from: 66 X, Z)
null - 55           (from: 55 Y, Z)
66 - null           (from: 66 X,)
null - 55           (from: 55 Y)
null - null         (from: 44 Z)