Feragatname
2014-12-01 Güncellemesi: Aşağıdaki yanıt yalnızca çok özel bir CSV biçimi için işe yarar. Doğru belirttiği gibi yorumlarında DG tarafından , bu çözüm yok değil CSV RFC 4180 tanımına uygun ve aynı zamanda yok değil Microsoft Excel biçimine uyacak. Bu çözüm, basitçe, dizelerin kaçan tırnak ve virgül içerebileceği dize türlerinin bir karışımını içeren bir (standart olmayan) CSV satırının nasıl ayrıştırılabileceğini gösterir.
Standart olmayan bir CSV çözümü
As austincheney doğru işaret , gerçekten düzgün kaçan karakterler içerebilir tırnakla idare etmek isterseniz baştan sona dize ayrıştırmak gerekir. Ayrıca OP, bir "CSV dizesinin" gerçekte ne olduğunu açıkça tanımlamaz. Öncelikle, geçerli bir CSV dizesini neyin oluşturduğunu ve bireysel değerlerini tanımlamalıyız.
Verilen: "CSV Dizesi" Tanımı
Bu tartışmanın amacı doğrultusunda, bir "CSV dizisi", birden çok değerin virgülle ayrıldığı sıfır veya daha fazla değerden oluşur. Her bir değer şunlardan oluşabilir:
- Çift tırnaklı bir dize (çıkış karaktersiz tek tırnaklar içerebilir).
- Tek tırnaklı bir dize (çıkış karaktersiz çift tırnak içerebilir).
- Olmayan bir alıntı dize (olabilir değil tırnak, virgül ve).
- Boş bir değer. (Tüm boşluklar boş olarak kabul edilir.)
Kurallar / Notlar:
- Alıntılanan değerler virgül içerebilir.
- Alıntılanan değerler kaçan herhangi bir şey içerebilir, ör
'that\'s cool'
.
- Tırnak işareti, virgül veya ters eğik çizgi içeren değerler tırnak içine alınmalıdır.
- Baştaki veya sondaki boşluk içeren değerler tırnak içine alınmalıdır.
- Ters eğik çizgi tüm:
\'
tek tırnaklı değerlerden kaldırılır .
- Ters eğik çizgi tüm:
\"
çift tırnaklı değerlerden kaldırılır .
- Alıntı yapılmamış dizeler, baştaki ve sondaki boşluklardan kırpılır.
- Virgül ayırıcı bitişik boşluklara sahip olabilir (ki bu yok sayılır).
Bul:
Geçerli bir CSV dizesini (yukarıda tanımlandığı gibi) bir dizi değerleri dizisine dönüştüren bir JavaScript işlevi.
Çözüm:
Bu çözüm tarafından kullanılan normal ifadeler karmaşıktır. Ve (IMHO) tüm önemsiz olmayan düzenli ifadeler, çok sayıda yorum ve girinti ile serbest aralık modunda sunulmalıdır. Maalesef, JavaScript serbest boşluk moduna izin vermiyor. Bu nedenle, bu çözüm tarafından uygulanan normal ifadeler ilk olarak yerel düzenli ifadeler sözdiziminde sunulur (Python'un kullanışlı r'''...'''
ham çok satırlı dizgi sözdizimi kullanılarak ifade edilir ).
Birincisi, bir CVS dizesinin yukarıdaki gereksinimleri karşıladığını doğrulayan normal bir ifadedir:
Bir "CSV dizesini" doğrulamak için normal ifade:
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.
"""
Bir dizge yukarıdaki normal ifadeyle eşleşirse, bu dize geçerli bir CSV dizesidir (daha önce belirtilen kurallara göre) ve aşağıdaki normal ifade kullanılarak ayrıştırılabilir. Aşağıdaki normal ifade daha sonra CSV dizesindeki bir değeri eşleştirmek için kullanılır. Daha fazla eşleşme bulunmayana (ve tüm değerler ayrıştırılana) kadar tekrar tekrar uygulanır.
Geçerli bir CSV dizesinden bir değeri ayrıştırmak için normal ifade:
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.
"""
Bu normal ifadenin eşleşmediği özel bir durum değeri vardır - bu değer boş olduğunda en son değer. Bu özel "boş son değer" durumu, aşağıdaki JavaScript işlevi için test edilir ve işlenir.
CSV dizesini ayrıştırmak için JavaScript işlevi:
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;
if (!re_valid.test(text)) return null;
var a = [];
text.replace(re_value,
function(m0, m1, m2, m3) {
if (m1 !== undefined) a.push(m1.replace(/\\'/g, "'"));
else if (m2 !== undefined) a.push(m2.replace(/\\"/g, '"'));
else if (m3 !== undefined) a.push(m3);
return '';
});
if (/,\s*$/.test(text)) a.push('');
return a;
};
Örnek giriş ve çıkış:
Aşağıdaki örneklerde {result strings}
,. (Bu, baştaki / sondaki boşlukları ve sıfır uzunluklu dizeleri görselleştirmeye yardımcı olmak içindir.)
var test = "'string, duppi, du', 23, lala";
var a = CSVtoArray(test);
var test = "";
var a = CSVtoArray(test);
var test = ",";
var a = CSVtoArray(test);
var test = "'one','two with escaped \' single quote', 'three, with, commas'";
var a = CSVtoArray(test);
var test = '"one","two with escaped \" double quote", "three, with, commas"';
var a = CSVtoArray(test);
var test = " one , 'two' , , ' four' ,, 'six ', ' seven ' , ";
var a = CSVtoArray(test);
Ek Notlar:
Bu çözüm, CSV dizesinin "geçerli" olmasını gerektirir. Örneğin, tırnaksız değerler ters eğik çizgi veya tırnak işareti içeremez, örneğin aşağıdaki CSV dizesi geçerli değildir :
var invalid1 = "one, that's me!, escaped \, comma"
Bu gerçekten bir sınırlama değildir, çünkü herhangi bir alt dizge tek veya çift tırnaklı bir değer olarak temsil edilebilir. Ayrıca bu çözümün "virgülle ayrılmış değerler" için yalnızca bir olası tanımı temsil ettiğine dikkat edin.
Geçmişi düzenle
- 2014-05-19: Sorumluluk reddi eklendi.
- 2014-12-01: Sorumluluk reddi en üste taşındı.