2010-02-11 4 views
1

Ok 이것은 영어로 설명하기가 어렵 기 때문에 예제를 제공 할 것입니다. 괄호보다 regexp에서 더 많은 역 참조 얻기

나는 다음과 같은 형식의 문자열을해야 할 것입니다 : (

key-value;key1-value;key2-... 

을하고 난 달성하기 위해 정규 표현식을 사용할 계획했다

array('key'=>'value','key1'=>'value1', ...) 

배열에게로 데이터를 추출 할 필요가 대부분 of)이 정규 표현식을 작성했습니다.

/^(\w+)-([^-;]+)(?:;(\w+)-([^-;]+))*;?$/ 

preg_match 및이 코드는

for ($l = count($matches),$i = 1;$i<$l;$i+=2) { 
    $parameters[$matches[$i]] = $matches[$i+1]; 
} 

그러나 정규 표현식은 입력 문자열의 첫 번째 및 마지막 키 - 값 쌍인 분명히 4 개의 하위 참조 만 반환합니다. 이 문제를 해결할 방법이 있습니까? 나는 문자열의 정확성을 테스트하고 PHP의 explode을 완벽한 결과를 가진 루프에서 사용하기 위해 정규 표현식을 사용할 수 있다는 것을 알고 있지만, 정규 표현식으로 가능한지 궁금하다.

간단히 말해서 정규 표현식을 사용하여 임의의 숫자의 문자열 (key-value; 쌍)을 캡처해야합니다.

답변

2

당신은 입력의 유효성을 검사하기 위해 내다을 사용할 수 있습니다. 입력이 유효하지 않은 경우, 즉시 일치는 실패하지만 정규 표현식이 적용될 때마다 lookahead는 여전히 평가됩니다.그것을 (정규 표현식의 나머지 부분과 함께) 키 - 값 쌍과 동기화하여 유지하기 위해 이전 일치가 끝난 지점에 각 일치를 앵커링하기 위해 \G을 사용했습니다.

이렇게하면 lookahead가 처음 성공한 경우 이후의 모든 시간에 성공할 수 있습니다. 분명히 가능한 한 효율적이지는 않지만, 문제가되지는 않을 것입니다. 테스트에서만 확실하게 알 수 있습니다.

미리보기가 실패하면 preg_match_all()은 0을 반환합니다. 성공하면 배열의 배열로 반환됩니다. 하나는 전체 키 - 값 쌍, 하나는 키, 하나는 값입니다.

0

아니요 최근 일치 항목이 더 오래된 일치 항목을 덮어 씁니다. 아마도 limit 인수가 explode() 일 때 폭발 할 때 도움이 될 것입니다.

2

정규식은 강력한 도구이지만 때로는 최상의 방법이 아닙니다.

$string = "key-value;key1-value"; 
$s = explode(";",$string); 
foreach($s as $k){ 
    $e = explode("-",$k); 
    $array[$e[0]]=$e[1]; 
} 
print_r($array); 
+0

감사합니다.하지만 OP에서 말했듯이 :'정규 표현식을 사용하여 문자열의 정확성을 테스트하고 PHP가 완벽한 결과로 루프에서 폭발 할 수 있음을 알고 있습니다. ' – raveren

+0

그래서 ...이 코드는 작동하지만, regex가 작업에 적합한 도구가 아니더라도 오히려 정규 표현식을 사용하기 때문에 그것을 사용하고 싶지 않습니다. 정규식이 진짜 요구 사항입니까 아니면 작동해야하기 때문에 그냥 그렇게하려고합니까? – David

+0

OP를 읽거나 다시 한 번 인용해야합니까? 단 두어 길이의 단락입니다. 읽으려면 너무 힘들다면 똑똑한 엉덩이의 말을 삼가하십시오. – raveren

2

preg_match_all()을 대신 사용하십시오. 아마 같은 :

$matches = $parameters = array(); 
$input = 'key-value;key1-value1;key2-value2;key123-value123;'; 

preg_match_all("/(\w+)-([^-;]+)/", $input, $matches, PREG_SET_ORDER); 

foreach ($matches as $match) { 
    $parameters[$match[1]] = $match[2]; 
} 

print_r($parameters); 

편집 :

if (preg_match("/^((\w+)-([^-;]+);)+$/", $input) > 0) { 
    /* do the preg_match_all stuff */ 
}  

EDIT2가 : 입력 문자열 패턴을 따르는 경우

가 먼저 바로 사용의 유효성을 검사 할 수있는 마지막 세미콜론은 선택 사항입니다

if (preg_match("/^(\w+-[^-;]+;)*\w+-[^-;]+$/", $input) > 0) { 
    /* do the preg_match_all stuff */ 
}  
+0

이것이 내 질문에 대한 유일한 대답이기 때문에 나는 아무에게도 더 나은 해결책을 제안하지 않으면 그것을 받아 들일 것이다. 그러나 정규 표현식은 주어진 문자열을 검증하지 않는다 (''foo-bar-baz '' 유효한 값으로 처리 될 것입니다.) – raveren

+0

''foo-bar-baz''에 대해''foo '=>'bar-baz'' 또는''foo-bar '=>'baz''를 원하십니까? 나는 대체 정규식을 쉽게 줄 수있다.) – Lukman

+0

''foo '=>'bar-baz ''정규식'/ (\ w +) - ([^;] +) /'대신 – Lukman

0

약 해결책 :

$samples = array(
    "good" => "key-value;key1-value;key2-value;key5-value;key-value;", 
    "bad1" => "key-value-value;key1-value;key2-value;key5-value;key-value;", 
    "bad2" => "key;key1-value;key2-value;key5-value;key-value;", 
    "bad3" => "k%ey;key1-value;key2-value;key5-value;key-value;" 
); 

foreach($samples as $name => $value) { 
    if (preg_match("/^(\w+-\w+;)+$/", $value)) { 
     printf("'%s' matches\n", $name); 
    } else { 
     printf("'%s' not matches\n", $name); 
    } 
} 
난 당신이 검증 및 데이터에 대한 preg_match_all()을위한 앵커 ( ^$)를 필요로하는 당신은, 하나 개의 정규 표현식으로 데이터를 모두 검증 및 추출을 할 수 있다고 생각하지만 preg_match_all()와 앵커를 사용하는 경우 그것은 것입니다하지 않습니다
+0

마지막 세미콜론';'은 필요하지 않습니다. 또한이 경우에만 입력을 확인, 정규식 확인하고 배열을 만들 싶습니다. – raveren

+0

네, 데이터가 필요하다는 것을 깨닫지 못했습니다. –

0

일치하는 마지막 세트 만 반환합니다.

/\G(?=(?:\w++-[^;-]++;?)++$)(\w++)-([^;-]++);?/ 

(?=(?:\w++-[^;-]++;?)++$) 유효성 검사 부분이다 : 당신이 경기를 추출하면서