2011-11-15 2 views
6

나는 그 얼굴에 단순 해 보이는 문제가 있지만 빈약 한 정규 표현식 기술을 깨뜨렸다. 배열로 변환 한 다음 적절하게 값을 처리해야하는 문자열이 있지만 문자열의 형식을 변경할 수 없습니다 (다른 곳에서 생성 됨). 논리로 인해 당황 스럽습니다.Regex를 사용하여 문자열을 2D 배열로 분할하는 방법?

문자열이다

그것은 기본적 ID 및 소수 값들의 세트이다
[6] [2] [3] 12.00; [5] [4] 

(이 경우에는 번호 3 == 12.00). ID의 양은 언제든지 변경 될 수 있으며 모든 십진수 값은 일부 또는 모든 ID에있을 수 있습니다.

Array (
    [0] => Array (
      [id] => 6 
      [num] => 
     ) 
    [1] => Array (
      [id] => 2 
      [num] => 
     ) 
    [2] => Array (
      [id] => 3 
      [num] => 12.00 
     ) 
    Etc... 

는 정규식 마법사의이는 내가 달성 할 수있었습니다보다 적은 맹세하여 수행 할 수있는 방법을 알고 계십니까 : 나는 다음과 같은 배열을 할 수있는 이상적인 세계에서는

?

내가 지금까지 사용하여 아이디의를 추출 할 수 있었다 :

preg_match_all('@\[(.*?)\]@s', $string, $array); 

과 소수 사용 :

preg_match_all('/([0-9]+[,\.]{1}[0-9]{2})/', $string, $array); 

하지만 ID 년대와 값 사이의 상관 관계를 잃게됩니다.

+1

당신이 폭발 및 성능의 용어에서 정규식보다는 그것의 더 나은 않는 strstr이 문제를 해결할 수 있습니다 (물론이 개선 될 수있다). – shox

답변

3

예 :

<?php 

$string = '[6] [2] [3] 12.00; [5] [4]'; 

preg_match_all('/\[(?P<id>\d+)\](?: (?P<num>[\d\.]+);)?/', $string, $matches, PREG_SET_ORDER); 

var_dump($matches); 

출력 :

array(5) { 
    [0]=> 
    array(3) { 
    [0]=> 
    string(3) "[6]" 
    ["id"]=> 
    string(1) "6" 
    [1]=> 
    string(1) "6" 
    } 
    [1]=> 
    array(3) { 
    [0]=> 
    string(3) "[2]" 
    ["id"]=> 
    string(1) "2" 
    [1]=> 
    string(1) "2" 
    } 
    [2]=> 
    array(5) { 
    [0]=> 
    string(10) "[3] 12.00;" 
    ["id"]=> 
    string(1) "3" 
    [1]=> 
    string(1) "3" 
    ["num"]=> 
    string(5) "12.00" 
    [2]=> 
    string(5) "12.00" 
    } 
    [3]=> 
    array(3) { 
    [0]=> 
    string(3) "[5]" 
    ["id"]=> 
    string(1) "5" 
    [1]=> 
    string(1) "5" 
    } 
    [4]=> 
    array(3) { 
    [0]=> 
    string(3) "[4]" 
    ["id"]=> 
    string(1) "4" 
    [1]=> 
    string(1) "4" 
    } 
} 
+1

@Gordon : Done and done. 제안 해 주셔서 감사합니다. :) –

+0

이것이 내가 스택 오버플로를 사랑하는 이유입니다. 그것은 절대적으로 완벽합니다! 정말 고마워요! –

+1

@Matthew Chambers : 천만에. :) –

1

당신은 목록에 만족하는 경우 중 하나 ID 또는 NUM을 입력하면 두 작업 범위를 결합 할 수 있습니다. 하나의 호출에 XES는 : 당신은 또한 PREG_SET_ORDER 플래그를 사용하는 경우

preg_match_all('@ \[(?P<id> \d+)] | (?P<num> [\d,.]+) @xs', 
     $string, $array, PREG_SET_ORDER); 

이, id 또는 num 중 하나 세트, 당신에게 연관 배열의 목록을 제공합니다.

1

이와 비슷한? 내 PHP 기술은 다소 약해서 명명 된 캡처 그룹 id/num에 액세스하는 방법을 확인해야합니다.

" 
\[    # Match the character “[” literally 
(?<id>   # Match the regular expression below and capture its match into backreference with name “id” 
    \d    # Match a single digit 0..9 
     +    # Between one and unlimited times, as many times as possible, giving back as needed (greedy) 
) 
]    # Match the character “]” literally 
\s    # Match a single character that is a “whitespace character” (spaces, tabs, line breaks, etc.) 
    *    # Between zero and unlimited times, as many times as possible, giving back as needed (greedy) 
(?<num>  # Match the regular expression below and capture its match into backreference with name “num” 
    [-+]   # Match a single character present in the list “-+” 
     ?    # Between zero and one times, as many times as possible, giving back as needed (greedy) 
    \b    # Assert position at a word boundary 
    [0-9]   # Match a single character in the range between “0” and “9” 
     +    # Between one and unlimited times, as many times as possible, giving back as needed (greedy) 
    (?:   # Match the regular expression below 
     \.    # Match the character “.” literally 
     [0-9]   # Match a single character in the range between “0” and “9” 
     +    # Between one and unlimited times, as many times as possible, giving back as needed (greedy) 
    )?    # Between zero and one times, as many times as possible, giving back as needed (greedy) 
    \b    # Assert position at a word boundary 
)?    # Between zero and one times, as many times as possible, giving back as needed (greedy) 
" 

또한 음의 값을 담당 : 작동 원리

preg_match_all('/\[(?P<id>\d+)\]\s*(?P<num>[-+]?\b[0-9]+(?:\.[0-9]+)?\b)?/', $subject, $result, PREG_SET_ORDER); 
for ($matchi = 0; $matchi < count($result); $matchi++) { 
    for ($backrefi = 0; $backrefi < count($result[$matchi]); $backrefi++) { 
     # Matched text = $result[$matchi][$backrefi]; 
    } 
} 

.

0

아니고 정규식 접근하지만 어쩌면 그것은 당신을 위해 작동 :

$str = "[6] [2] [3] 12.00; [5] [4]"; 
$str = str_replace(array('[',']'), '', $str); 

$arr = explode(' ', $str); 
$array = array(); 
for($i=0 ; $i < count($arr) ; $i++) 
{ 
    $isValue = strpos($arr[$i], '.'); 
    if($isValue !== false){ 
     continue; 
    } 

    $key = $arr[$i]; 
    $ret = array('id' => $key , 'num' => ''); 

    $nextIsFloat = strstr($arr[$i+1], ';', TRUE); 
    if(!$nextIsFloat){ 
     $array[] = $ret;   
     continue; 
    }else{ 
     $ret['num'] = $nextIsFloat; 
     $array[] = $ret; 
     $i++;  
    } 
} 
관련 문제