부인 성명
2014-12-01 업데이트 : 아래 답변은 매우 구체적인 CSV 형식에만 적용됩니다. 의견에서 DG가 올바르게 지적했듯이이 솔루션은 CSV의 RFC 4180 정의에 맞지 않으며 MS Excel 형식에도 맞지 않습니다. 이 솔루션은 문자열에 이스케이프 된 따옴표와 쉼표가 포함될 수있는 문자열 유형의 혼합을 포함하는 하나의 (비표준) CSV 입력 행을 구문 분석하는 방법을 보여줍니다.
비표준 CSV 솔루션
austincheney가 올바르게 지적했듯이, 이스케이프 된 문자를 포함 할 수있는 따옴표로 묶인 문자열을 올바르게 처리하려면 문자열을 처음부터 끝까지 구문 분석해야합니다. 또한 OP는 "CSV 문자열"이 실제로 무엇인지 명확하게 정의하지 않습니다. 먼저 유효한 CSV 문자열과 개별 값을 구성하는 항목을 정의해야합니다.
주어진 : "CSV 문자열"정의
이 설명을 위해 "CSV 문자열"은 0 개 이상의 값으로 구성되며 여러 값은 쉼표로 구분됩니다. 각 값은 다음으로 구성 될 수 있습니다.
- 큰 따옴표로 묶인 문자열. (이스케이프 처리되지 않은 작은 따옴표를 포함 할 수 있습니다.)
- 작은 따옴표로 묶인 문자열. (이스케이프 처리되지 않은 큰 따옴표를 포함 할 수 있습니다.)
- 인용되지 않은 문자열입니다. (따옴표, 쉼표 또는 백 슬래시를 포함 할 수 없습니다.)
- 빈 값. (모두 공백 값은 비어있는 것으로 간주됩니다.)
규칙 / 참고 :
- 인용 된 값에는 쉼표가 포함될 수 있습니다.
- 인용 된 값은 이스케이프 된 모든 것을 포함 할 수 있습니다
'that\'s cool'
.
- 따옴표, 쉼표 또는 백 슬래시가 포함 된 값은 따옴표로 묶어야합니다.
- 선행 또는 후행 공백이 포함 된 값은 따옴표로 묶어야합니다.
- 백 슬래시는 모두에서 제거됩니다 :
\'
작은 따옴표로 묶인 값.
- 백 슬래시는 모두에서 제거됩니다 :
\"
큰 따옴표로 묶인 값.
- 인용되지 않은 문자열은 선행 및 후행 공백이 제거됩니다.
- 쉼표 구분 기호에 인접한 공백이있을 수 있습니다 (무시 됨).
찾기:
유효한 CSV 문자열 (위에 정의 된대로)을 문자열 값의 배열로 변환하는 JavaScript 함수입니다.
해결책:
이 솔루션에서 사용하는 정규식은 복잡합니다. 그리고 (IMHO) 모든 중요하지 않은 정규식은 많은 주석과 들여 쓰기와 함께 자유 간격 모드로 표시되어야합니다. 안타깝게도 JavaScript는 자유 간격 모드를 허용하지 않습니다. 따라서이 솔루션에 의해 구현 된 정규식은 먼저 기본 정규식 구문으로 표시됩니다 (Python의 편리한 : r'''...'''
raw-multi-line-string 구문을 사용하여 표현됨 ).
먼저 여기에 CVS 문자열이 위의 요구 사항을 충족하는지 확인하는 정규식이 있습니다.
"CSV 문자열"의 유효성을 검사하는 정규식 :
re_valid = r"""
# Validate a CSV string having single, double or un-quoted values.
^ # Anchor to start of string.
\s* # Allow whitespace before value.
(?: # Group for value alternatives.
'[^'\\]*(?:\\[\S\s][^'\\]*)*' # Either Single quoted string,
| "[^"\\]*(?:\\[\S\s][^"\\]*)*" # or Double quoted string,
| [^,'"\s\\]*(?:\s+[^,'"\s\\]+)* # or Non-comma, non-quote stuff.
) # End group of value alternatives.
\s* # Allow whitespace after value.
(?: # Zero or more additional values
, # Values separated by a comma.
\s* # Allow whitespace before value.
(?: # Group for value alternatives.
'[^'\\]*(?:\\[\S\s][^'\\]*)*' # Either Single quoted string,
| "[^"\\]*(?:\\[\S\s][^"\\]*)*" # or Double quoted string,
| [^,'"\s\\]*(?:\s+[^,'"\s\\]+)* # or Non-comma, non-quote stuff.
) # End group of value alternatives.
\s* # Allow whitespace after value.
)* # Zero or more additional values
$ # Anchor to end of string.
"""
문자열이 위의 정규식과 일치하면 해당 문자열은 유효한 CSV 문자열 (이전에 언급 한 규칙에 따라)이며 다음 정규식을 사용하여 구문 분석 할 수 있습니다. 그런 다음 다음 정규식을 사용하여 CSV 문자열에서 하나의 값을 일치시킵니다. 더 이상 일치하는 항목이없고 모든 값이 구문 분석 될 때까지 반복적으로 적용됩니다.
유효한 CSV 문자열에서 하나의 값을 구문 분석하는 정규식 :
re_value = r"""
# Match one value in valid CSV string.
(?!\s*$) # Don't match empty last value.
\s* # Strip whitespace before value.
(?: # Group for value alternatives.
'([^'\\]*(?:\\[\S\s][^'\\]*)*)' # Either $1: Single quoted string,
| "([^"\\]*(?:\\[\S\s][^"\\]*)*)" # or $2: Double quoted string,
| ([^,'"\s\\]*(?:\s+[^,'"\s\\]+)*) # or $3: Non-comma, non-quote stuff.
) # End group of value alternatives.
\s* # Strip whitespace after value.
(?:,|$) # Field ends on comma or EOS.
"""
이 정규식이 일치하지 않는 특별한 경우 값이 하나 있습니다. 해당 값이 비어있을 때 가장 마지막 값입니다. 이 특별한 "빈 마지막 값" 케이스는 뒤에 오는 js 함수에 의해 테스트되고 처리됩니다.
CSV 문자열을 구문 분석하는 JavaScript 함수 :
// Return array of string values, or NULL if CSV string not well formed.
function CSVtoArray(text) {
var re_valid = /^\s*(?:'[^'\\]*(?:\\[\S\s][^'\\]*)*'|"[^"\\]*(?:\\[\S\s][^"\\]*)*"|[^,'"\s\\]*(?:\s+[^,'"\s\\]+)*)\s*(?:,\s*(?:'[^'\\]*(?:\\[\S\s][^'\\]*)*'|"[^"\\]*(?:\\[\S\s][^"\\]*)*"|[^,'"\s\\]*(?:\s+[^,'"\s\\]+)*)\s*)*$/;
var re_value = /(?!\s*$)\s*(?:'([^'\\]*(?:\\[\S\s][^'\\]*)*)'|"([^"\\]*(?:\\[\S\s][^"\\]*)*)"|([^,'"\s\\]*(?:\s+[^,'"\s\\]+)*))\s*(?:,|$)/g;
// Return NULL if input string is not well formed CSV string.
if (!re_valid.test(text)) return null;
var a = []; // Initialize array to receive values.
text.replace(re_value, // "Walk" the string using replace with callback.
function(m0, m1, m2, m3) {
// Remove backslash from \' in single quoted values.
if (m1 !== undefined) a.push(m1.replace(/\\'/g, "'"));
// Remove backslash from \" in double quoted values.
else if (m2 !== undefined) a.push(m2.replace(/\\"/g, '"'));
else if (m3 !== undefined) a.push(m3);
return ''; // Return empty string.
});
// Handle special case of empty last value.
if (/,\s*$/.test(text)) a.push('');
return a;
};
입력 및 출력 예 :
다음 예에서는 중괄호를 사용하여 {result strings}
. (이것은 선행 / 후행 공백과 길이가 0 인 문자열을 시각화하는 데 도움이됩니다.)
// Test 1: Test string from original question.
var test = "'string, duppi, du', 23, lala";
var a = CSVtoArray(test);
/* Array hes 3 elements:
a[0] = {string, duppi, du}
a[1] = {23}
a[2] = {lala} */
// Test 2: Empty CSV string.
var test = "";
var a = CSVtoArray(test);
/* Array hes 0 elements: */
// Test 3: CSV string with two empty values.
var test = ",";
var a = CSVtoArray(test);
/* Array hes 2 elements:
a[0] = {}
a[1] = {} */
// Test 4: Double quoted CSV string having single quoted values.
var test = "'one','two with escaped \' single quote', 'three, with, commas'";
var a = CSVtoArray(test);
/* Array hes 3 elements:
a[0] = {one}
a[1] = {two with escaped ' single quote}
a[2] = {three, with, commas} */
// Test 5: Single quoted CSV string having double quoted values.
var test = '"one","two with escaped \" double quote", "three, with, commas"';
var a = CSVtoArray(test);
/* Array hes 3 elements:
a[0] = {one}
a[1] = {two with escaped " double quote}
a[2] = {three, with, commas} */
// Test 6: CSV string with whitespace in and around empty and non-empty values.
var test = " one , 'two' , , ' four' ,, 'six ', ' seven ' , ";
var a = CSVtoArray(test);
/* Array hes 8 elements:
a[0] = {one}
a[1] = {two}
a[2] = {}
a[3] = { four}
a[4] = {}
a[5] = {six }
a[6] = { seven }
a[7] = {} */
추가 참고 사항 :
이 솔루션을 사용하려면 CSV 문자열이 "유효"해야합니다. 예를 들어 따옴표가없는 값에는 백 슬래시 또는 따옴표가 포함될 수 없습니다. 예를 들어 다음 CSV 문자열은 유효하지 않습니다.
var invalid1 = "one, that's me!, escaped \, comma"
하위 문자열이 작은 따옴표 또는 큰 따옴표 값으로 표현 될 수 있기 때문에 이것은 실제로 제한이 아닙니다. 또한이 솔루션은 "쉼표로 구분 된 값"에 대한 하나의 가능한 정의 만 나타냅니다.
편집 : 2014-05-19 : 면책 조항 추가.
편집 : 2014-12-01 : 면책 조항을 맨 위로 이동했습니다.