PHP preg_match_all () - Что не так с моим регулярным выражением? - PullRequest
1 голос
/ 24 марта 2011

Вот пример строки:

---------
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 () и преобразует массив $ match в более удобный для использования массив:

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

И вот результирующий массив:

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

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

)

Итак, я хочу вернуть всю информацию о медиках (идентификатор, роль и уровень), но я не хочу, чтобы шаблон зависел от какой-либо части информации, находящейся там - поэтому он должен вернуть медика, если любая из этих точек данных присутствует.

Ответы [ 2 ]

1 голос
/ 24 марта 2011

Вы можете в значительной степени устранить ручное назначение цикла, используя именованные группы захвата:

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
    )
1 голос
/ 24 марта 2011

Это должно сработать:

^ ID ЭКИПАЖА: (. *) РОЛЬ ЧЛЕНА ЭКИПАЖА: (. *) УРОВЕНЬ ЭКИПАЖА: (. *) $

по крайней мере, это работает для приведенного вами примера. Но ". +?" и звездочки "*" между полями могут означать, что вы хотите, чтобы они были необязательными, или вы хотите разрешить более одного. Поэтому, возможно, вам нужно предоставить больше примеров ...

Кстати: если вы хотите, чтобы строка точно совпадала, используйте ^ $. и активировать опцию, которая позволяет ^ $ соответствовать разрывам строк. Я # не хочу использовать "\ n"

...