2012-01-17 5 views
0

파서를 사용하지 않고 CSV 파일에서 한 행을 추출하려고하고 있습니다. PHP를 사용하여 쉼표를 기준으로 문자열을 분할해야합니다. . 입력에 쉼표가 없다면 그 자체로는 매우 쉽습니다. 큰 따옴표로 묶인 쉼표를 무시하고 싶습니다. 완전히 마지막 문장을 무시 Regex : 큰 따옴표가 0 번 또는 홀수 번 반복 된 후 일치 ','

, 나는 다음 문제 자체를 변경하기로 결정 :

나는 더 큰 따옴표 앞에 나 큰 따옴표 쌍을 흩어져 쉼표에 따라 문자열을 분할 할

.

예 : *이 일치하고 X입니다

text,"some,"chars,chars"more,""text", 
    *  x  *   x  * 

는 없습니다.

정규 표현식의 기능을 넘어서는가? 그렇지 않은 경우 이런 종류의 입력을 처리 할 수있는 정규 표현식이 있습니까?

+3

입니까? 덧붙여 말하자면 "within"이 이스케이프되어야하거나 "some"와 같은 blob을 가지고있을 때 적절하게 인용되지 않은 문자가 –

+0

일 수 있으니 예제 문자열은 유효하지 않을 수 있습니다. 'fgetcsv()'와 같은 것을 사용하면보다 쉽게 ​​파싱을 할 수 있습니다. – Arjan

+0

할 수 있습니다. 실제로 하나는 가지고 있지만 표준 CSV 규칙에 더 부합합니다. 이스케이프 변형 및 값어치가 혼합 된 따옴표/인용되지 않은 문자열 부분이 아닙니다. – mario

답변

1

내가 여기이 훨씬 좋네요 쓸 수 있습니다 확신 해요,하지만 당신의 경우에 작동하는 변종 :

preg_match_all('/ 
    \s* ((?: (?=.|(?<=,)$) [^",]* | "(?: ""|[^"]*)+")+) \s* (?:,|$) /xms', 
    $line, $matches 
) 
and print_r($matches[1]); 

그러나 다른 일반적인 CSV 규칙을 준수하지 않습니다. 나는 일반적으로 \"을 이스케이프 된 큰 따옴표로 간주합니다. 그리고 따옴표로 묶인 따옴표로 묶지 않은 부분 문자열도 매우 비표준입니다. 그리고 어떤 형태의 검증도 부족하기 때문에 정확하게 쌍을 이루지 못하면 마지막 인용을 간과 할 것입니다. 테스트 문자열

:

 [0] => text 
     [1] => "some,"chars 
     [2] => chars"more,""text" 
     [3] => 
1

CSV 파일이 올바른 경우 (각 필드는 시작과 끝 중 하나, 당신은 재귀 함수로 문자열을 구문 분석 할 수 "또는이 포함되어 있지 않습니다" 과 같이 :.

이가 (탈출) 포함 인용 문자열 테스트되지 않았 음을
$csvString = 'zero,"o,ne",two,"thr,ee"'; 

function parseCsv($string, &$result) 
{ 
    $regex = '/^((".*")|([^"].*))(,(.*))?$/U'; 
    $matches = array(); 
    preg_match($regex, $string, $matches); 
    $result[] = $matches[1]; 
    if(isset($matches[5])) 
    { 
     parseCsv($matches[5], $result); 
    } 
} 

$result = array(); 
parseCsv($csvString, $result); 

var_dump($result); 

참고 인용 또한 그것은 주변에 인용 된 문자열 따옴표를 유지

의 결과입니다. 위의 함수는 str_getcsv() http://uk3.php.net/manual/en/function.str-getcsv.php를 사용하지 않는 이유는 특별한 이유가

array 
    0 => string 'zero' (length=4) 
    1 => string '"o,ne"' (length=6) 
    2 => string 'two' (length=3) 
    3 => string '"thr,ee"' (length=8)