开发者

PHP preg_match_all() - What's wrong with my regex?

开发者 https://www.devze.com 2023-02-19 19:00 出处:网络
Here is a sample string: --------- SAY WHAAAAT MEDICS: CREW ID: PMD205304 CREW MEMBER ROLE: PRIMARY PATIENT CAREGIVER CREW MEMBER LEVEL: EMT-PARAMEDIC

Here is a sample string:

---------
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

And this is the function that performs the preg_match_all() and translates the $matches array into a more usable array:

      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>";
        }       
  }

And here is the resulting array:

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

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

)

So what I want is to return all of the medic info (ID, role & level), but I don't want the pattern to be dependent on any one piece of info being there - So it should return the medic if any one of those data points are present.


You can pretty much eliminate the manual loop assignment by using named capture groups:

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

This will result in a many extranous entries, but [id] and [role] and [level] are already separated out (of course you can add ?: again to reduce the clutter):

[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
    )


This should do the trick:

^CREW ID: (.*) CREW MEMBER ROLE: (.*) CREW MEMBER LEVEL: (.*)$

at least it works for the example you provided. But the ".+?" and stars "*" between the fields could mean you want them to be optional or you want to allow more than one. So maybe you need to provide more examples...

BTW: If you want to ensure the line matches exactly use ^$. and to activate the option that allows ^$ to match line breaks. I#d rather not use "\n"

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号