PHP preg_match_all() - 我的正则表达式出了什么问题?

时间:2011-03-24 17:42:27

标签: php regex arrays preg-match-all

以下是一个示例字符串:

---------
SAY WHAAAAT
MEDICS:
CREW ID: PMD205304 CREW MEMBER ROLE: PRIMARY PATIENT CAREGIVER CREW MEMBER LEVEL: EMT-PARAMEDIC
CREW ID: EMT530755 CREW MEMBER ROLE: OTHER CREW MEMBER LEVEL: EMT-BASIC

这是执行preg_match_all()并将$ matches数组转换为更可用的数组的函数:

      private function getMedics(){
        if(isset($this->record->elements["E04"])){
              //REGEX:
              $ptn = "/(?:CREW ID: (.+?) )*(?:CREW MEMBER ROLE: (.+?)\s+)*(?:CREW MEMBER LEVEL: (.+))?\n/";
              $str = $this->record->incidentRow['Narrative']; //Column where medic info is stored in CodeZoneIncidents table
              preg_match_all($ptn,$str,$matches);
              foreach($matches as $key => $val){
                  foreach($matches[$key] as $key2 => $val2){
                      if(trim($val2) != ""){
                          $tmp[$key2]['ID'] = $matches[1][$key2];
                          $tmp[$key2]['role'] = $matches[2][$key2];
                          $tmp[$key2]['level'] = $matches[3][$key2];
                      }
                  }
              }
              $ii = 0;
              foreach($tmp as $key => $val){
                  $CZMedics[$ii]['ID'] = $tmp[$key]['ID'];
                  $CZMedics[$ii]['role'] = $tmp[$key]['role'];
                  $CZMedics[$ii]['level'] = $tmp[$key]['level'];
                  $ii++;
              } //REGEX pattern

              $iterations = $this->eleQTY($this->record->elements["E04"]); //Return how many E04 there are
              for($i=0; $i<$iterations; $i++){
                    //[E04][0] if there are multiples:
                    $tmpEle = (isset($this->record->elements["E04"][$i])?$this->record->elements["E04"][$i]:$this->record->elements["E04"]);
                    //Populate Actual values:
                    if(isset($tmpEle["E04_01"]->code)){
                          $tmpEle["E04_01"]->actual = fncIsSet($CZMedics[$i]['ID']); //Medic ID
                          $tmpEle["E04_01"]->CZCellName = "Narrative_Box"; //CZPopUp Box
                    }
                    if(isset($tmpEle["E04_02"]->code)){
                          $tmpEle["E04_02"]->actual = fncIsSet($CZMedics[$i]['role']); //Role
                          $tmpEle["E04_02"]->CZCellName = "Narrative_Box"; //CZPopUp Box
                    }
                    if(isset($tmpEle["E04_03"]->code)){
                          $tmpEle["E04_03"]->actual = fncIsSet($CZMedics[$i]['level']); //Level
                          $tmpEle["E04_03"]->CZCellName = "Narrative_Box"; //CZPopUp Box
                    }
              }
              echo "<pre style='display:none;'>!!!";
              print_r($CZMedics);
              echo "</pre>";
        }       
  }

这是结果数组:

Array
(
    [0] => Array
        (
            [ID] => PMD205304
            [role] => PRIMARY PATIENT CAREGIVER
            [level] => EMT-PARAMEDIC
        )

[1] => Array
    (
        [ID] => 
        [role] => 
        [level] => 
    )

所以我想要的是返回所有医疗信息(ID,角色和级别),但我不希望模式依赖于那里的任何一条信息 - 所以它应该返回医生如果存在任何一个数据点。

2 个答案:

答案 0 :(得分:1)

这应该可以解决问题:

^船员ID:(。*)船员会员角色:(。*)船员会员等级:(。*)$

至少它适用于您提供的示例。但是“。+?”字段之间的星号“*”可能意味着您希望它们是可选的,或者您希望允许多个字段。所以也许你需要提供更多的例子......

BTW:如果你想确保线匹配正好使用^ $。并激活允许^ $匹配换行符的选项。我不想使用“\ n”

答案 1 :(得分:1)

通过使用命名捕获组,您几乎可以消除手动循环分配:

preg_match_all('~^(?=CREW)(CREW ID: (?P<id>\w+))?\s*(CREW MEMBER ROLE: (?<role>.*?))?\s*(CREW MEMBER LEVEL: (?<level>.*?))?$~mi', $text, $match, PREG_SET_ORDER);

这将导致许多不同的条目,但[id][role]以及[level]已经分开(当然,您可以再次添加?:以减少混乱):

[0] => Array
    (
        [0] => CREW ID: PMD205304 CREW MEMBER ROLE: PRIMARY PATIENT CAREGIVER CREW MEMBER LEVEL: EMT-PARAMEDIC
        [1] => CREW ID: PMD205304
        [id] => PMD205304
        [2] => PMD205304
        [3] =>  CREW MEMBER ROLE: PRIMARY PATIENT CAREGIVER
        [role] => PRIMARY PATIENT CAREGIVER
        [4] => PRIMARY PATIENT CAREGIVER
        [5] =>  CREW MEMBER LEVEL: EMT-PARAMEDIC
        [level] => EMT-PARAMEDIC
        [6] => EMT-PARAMEDIC
    )