আমি কীভাবে জাভাস্ক্রিপ্টের একটি সিএসভি স্ট্রিংকে পার্স করতে পারি, এতে ডেটাতে কমা রয়েছে?


98

আমার কাছে নিম্নলিখিত ধরণের স্ট্রিং রয়েছে

var string = "'string, duppi, du', 23, lala"

আমি প্রতিটি কমাতে স্ট্রিংকে একটি অ্যারেতে বিভক্ত করতে চাই, তবে একক উদ্ধৃতি চিহ্নের বাইরে কেবল কমা।

আমি বিভাজনের জন্য সঠিক নিয়মিত প্রকাশটি বের করতে পারি না ...

string.split(/,/)

আমাকে দেবে

["'string", " duppi", " du'", " 23", " lala"]

তবে ফলাফলটি হওয়া উচিত:

["string, duppi, du", "23", "lala"]

একটি ক্রস ব্রাউজার সমাধান আছে?


এটি কি সর্বদা একক-কোট? উদ্ধৃত স্ট্রিংয়ের ভিতরে কি কখনও একক-উদ্ধৃতি রয়েছে? যদি তা হয় তবে কীভাবে এটি পালিয়ে যায় (ব্যাকস্ল্যাশ, দ্বিগুণ)?
ফ্রেগজ

জাভাস্ক্রিপ্ট এবং এইচটিএমএল / এক্সএমএল কোডের মতো যদি উদ্ধৃতি অক্ষরগুলি ডাবল এবং একক উদ্ধৃতি অক্ষরের মধ্যে সম্পূর্ণরূপে বিনিময়যোগ্য হয়? যদি তা হয় তবে এর জন্য আরও বিস্তৃত পার্সিং অপারেশন দরকার যা সিএসভি।
অস্টিচেন্নি

আসলে হ্যাঁ, ভিতরে একটি উদ্ধৃতি থাকতে পারে, ব্যাকস্ল্যাশ দিয়ে পালানো ঠিক হবে be
হ্যান্স

একটি মান একটি ডাবল উদ্ধৃত স্ট্রিং হতে পারে?
রডগারুনার

4
পাপা পার্সে ভাল কাজ করে। জাভাস্ক্রিপ্ট এবং পাপা পার্সের
রাফায়েল

উত্তর:


217

অস্বীকৃতি

2014-12-01 আপডেট: নীচের উত্তরগুলি কেবলমাত্র CSV এর একটি খুব নির্দিষ্ট বিন্যাসের জন্য কাজ করে। হিসাবে সঠিকভাবে নির্দিষ্ট মন্তব্য ডিজি দ্বারা , এই সমাধান নেই না করা CSV এর জন্য RFC 4180 সংজ্ঞা মাপসই এবং এটি নেই না মাইক্রোসফট এক্সেল ফরম্যাটে মাপসই করা হবে। এই সমাধানটি সহজভাবে দেখায় যে কীভাবে কেউ ইনপুটটির একটি (অ-মানক) সিএসভি লাইনকে পার্স করতে পারে যার মধ্যে স্ট্রিং প্রকারের মিশ্রণ রয়েছে, যেখানে স্ট্রিংগুলিতে অবরুদ্ধ উদ্ধৃতি এবং কমা থাকতে পারে।

একটি অ-মানক সিএসভি সমাধান

অস্টিচেনি যেমন সঠিকভাবে উল্লেখ করেছে , আপনি যদি উদ্ধৃত অক্ষরগুলি থাকতে পারে এমন উদ্ধৃত স্ট্রিংগুলি সঠিকভাবে পরিচালনা করতে চান তবে আপনাকে শুরু থেকে স্ট্রিংটি শেষ করতে হবে। এছাড়াও, ওপিস একটি "সিএসভি স্ট্রিং" আসলে কী তা স্পষ্টভাবে সংজ্ঞায়িত করে না। প্রথমে আমাদের একটি বৈধ সিএসভি স্ট্রিং এবং এর স্বতন্ত্র মানগুলি নির্ধারণ করতে হবে।

প্রদত্ত: "সিএসভি স্ট্রিং" সংজ্ঞা

এই আলোচনার উদ্দেশ্যে, একটি "সিএসভি স্ট্রিং" শূন্য বা তার বেশি মান নিয়ে গঠিত, যেখানে একাধিক মান কমা দ্বারা পৃথক করা হয়। প্রতিটি মান সমন্বিত হতে পারে:

  1. একটি দ্বিগুণ উদ্ধৃত স্ট্রিং (আনসকেপড একক উদ্ধৃতি থাকতে পারে)।
  2. একটি একক উদ্ধৃত স্ট্রিং (আনসকেপড ডাবল কোটস থাকতে পারে)।
  3. একটি অ-উদ্ধৃত স্ট্রিং ( কোটস, কমা বা ব্যাকস্ল্যাশ নাও থাকতে পারে)।
  4. একটি ফাঁকা মান (একটি সমস্ত সাদা স্থান মান শূন্য বিবেচনা করা হয়।)

বিধি / নোট:

  • উদ্ধৃত মানগুলিতে কমা থাকতে পারে।
  • উদ্ধৃত মানগুলিতে পালানো কিছু থাকতে পারে, যেমন 'that\'s cool'
  • উদ্ধৃতি, কমা বা ব্যাকস্ল্যাশযুক্ত মানগুলি অবশ্যই উদ্ধৃত করা উচিত।
  • শীর্ষস্থানীয় বা পিছনের শ্বেত স্পেসযুক্ত মানগুলি অবশ্যই উদ্ধৃত করা উচিত।
  • ব্যাকস্ল্যাশ সকল থেকে সরানো হয়েছে: \'একক উদ্ধৃত মানগুলিতে।
  • ব্যাকস্ল্যাশ সকল থেকে সরানো হয়েছে: \"ডাবল উদ্ধৃত মানগুলিতে।
  • অ-উদ্ধৃতিযুক্ত স্ট্রিংগুলি কোনও নেতৃস্থানীয় এবং পিছনে স্থানগুলি ছাঁটাই করা হয়।
  • কমা বিভাজকের নিকটবর্তী সাদা স্থান থাকতে পারে (যা উপেক্ষা করা হবে)।

অনুসন্ধান:

একটি জাভাস্ক্রিপ্ট ফাংশন যা কোনও বৈধ সিএসভি স্ট্রিংকে (উপরে সংজ্ঞায়িত করা) স্ট্রিং মানগুলির অ্যারে রূপান্তর করে।

সমাধান:

এই সমাধানটি দ্বারা ব্যবহৃত নিয়মিত প্রকাশগুলি জটিল। এবং (আইএমএইচও) সমস্ত অ-তুচ্ছ নিয়মিত অভিব্যক্তিগুলি প্রচুর মন্তব্য এবং ইন্ডেন্টেশন সহ ফ্রি-স্পেসিং মোডে উপস্থাপন করা উচিত। দুর্ভাগ্যক্রমে, জাভাস্ক্রিপ্ট ফ্রি-স্পেসিং মোডের অনুমতি দেয় না। সুতরাং, এই সমাধান দ্বারা প্রয়োগ করা নিয়মিত প্রকাশগুলি প্রথমে স্থানীয় নিয়মিত এক্সপ্রেশন বাক্য বাক্য গঠন উপস্থাপন করা হয় (পাইথনের হ্যান্ডি r'''...'''কাঁচা-মাল্টি-লাইন-স্ট্রিং সিনট্যাক্স ব্যবহার করে প্রকাশ করা হয় )।

প্রথমে এখানে একটি নিয়মিত প্রকাশ যা একটি সিভিএস স্ট্রিং উপরের প্রয়োজনীয়তাগুলি পূরণ করে যাচাই করে:

একটি "সিএসভি স্ট্রিং" যাচাই করার জন্য নিয়মিত অভিব্যক্তি:

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.
"""

মনে রাখবেন যে এখানে একটি বিশেষ কেস মান রয়েছে যা এই নিয়মিত প্রকাশের সাথে মেলে না - যখন সর্বশেষ মানটি শূন্য থাকে। এই বিশেষ "খালি সর্বশেষ মান" কেসটি জাভাস্ক্রিপ্ট ফাংশনটির জন্য পরীক্ষা করা হয় এবং পরিচালনা করা হয় যা অনুসরণ করে follows

সিএসভি স্ট্রিং পার্স করতে জাভাস্ক্রিপ্ট ফাংশন:

// 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}। (এটি শীর্ষস্থানীয় / পিছনে স্থান এবং শূন্য দৈর্ঘ্যের স্ট্রিংগুলি ভিজ্যুয়ালাইজ করতে সহায়তা করার জন্য))

// Test 1: Test string from original question.
var test = "'string, duppi, du', 23, lala";
var a = CSVtoArray(test);
/* Array has three elements:
    a[0] = {string, duppi, du}
    a[1] = {23}
    a[2] = {lala} */
// Test 2: Empty CSV string.
var test = "";
var a = CSVtoArray(test);
/* Array has zero elements: */
// Test 3: CSV string with two empty values.
var test = ",";
var a = CSVtoArray(test);
/* Array has two 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 has three 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 has three 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 has eight elements:
    a[0] = {one}
    a[1] = {two}
    a[2] = {}
    a[3] = { four}
    a[4] = {}
    a[5] = {six }
    a[6] = { seven }
    a[7] = {} */

অতিরিক্ত নোট:

এই সমাধানের জন্য সিএসভি স্ট্রিংটি "বৈধ" হওয়া দরকার। উদাহরণস্বরূপ, unquoted মান ব্যাকস্ল্যাশ বা উদ্ধৃতি, যেমন নিম্নলিখিত যে CSV স্ট্রিং নাও থাকতে পারে না বৈধ:

var invalid1 = "one, that's me!, escaped \, comma"

এটি প্রকৃতপক্ষে কোনও সীমাবদ্ধতা নয় কারণ যে কোনও উপ-স্ট্রিংকে একক বা ডাবল উদ্ধৃত মান হিসাবে উপস্থাপন করা যেতে পারে। এছাড়াও দ্রষ্টব্য যে এই সমাধানটি "কমা-বিভাজিত মানগুলির" জন্য কেবলমাত্র একটি সম্ভাব্য সংজ্ঞা উপস্থাপন করে।

ইতিহাস সম্পাদনা করুন

  • 2014-05-19: অস্বীকৃতি যুক্ত করা হয়েছে।
  • 2014-12-01: অস্বীকৃতি শীর্ষে সরানো হয়েছে।

4
@ ইভান প্লেইস - সুন্দর কথার জন্য ধন্যবাদ। আপনি যে কোনও বিভাজক ব্যবহার করতে পারবেন তা নিশ্চিত। আমার রেজেেক্সের প্রতিটি কমা কেবল পছন্দের বিভাজকের সাথে প্রতিস্থাপন করুন (তবে বিভাজকটি সাদা স্থান হতে পারে না)। চিয়ার্স
রডগারুনার

4
@ ইভান প্লেইস - আপনি যে কোনও উদ্দেশ্যে ইচ্ছা করে আমার যে কোনও রেইগেক্স ব্যবহার করতে আপনাকে স্বাগত জানাই। স্বীকৃতি একটি নোট চমৎকার হবে কিন্তু প্রয়োজন হবে না। আপনার প্লাগ-ইন দিয়ে শুভ কামনা। চিয়ার্স!
ridgerunner

4
দুর্দান্ত, এখানে প্রকল্প কোড . google.com/p/jquery-csv । অবশেষে, আমি সিএসভিতে একটি এক্সটেনশন ফর্ম্যাট যুক্ত করতে চাই (এসএসভিভি (কাঠামোগত পৃথক মান) যা কেবল সিএসভি যা মেটাডেটা (যেমন, ডিলিমিটার, বিভাজক, লাইন সমাপ্তি ইত্যাদি) অন্তর্ভুক্ত।
ইভান প্লেস

4
এই দুর্দান্ত বাস্তবায়নের জন্য অনেক ধন্যবাদ - আমি এটি নোড.জেএস মডিউল ( সিএসভি-পুনরুক্তি ) এর ভিত্তি হিসাবে ব্যবহার করেছি ।
মিরকোকিফার

4
আমি আপনার জবাবের বিশদ এবং স্পষ্টতাকে প্রশংসা করি, তবে এটি কোথাও লক্ষ করা উচিত যে আপনার সিএসভির সংজ্ঞা আরএফসি 4180 এর সাথে খাপ খায় না যা সিএসভি-র একটি মানদণ্ডের কাছে বন্ধ হওয়া জিনিস, এবং আমি বলতে পারি যে উপাখ্যানটি সাধারণত ব্যবহৃত হয়। বিশেষত স্ট্রিংয়ের ক্ষেত্রের মধ্যে ডাবল উদ্ধৃতি চরিত্রটি "পালানোর" এটাই স্বাভাবিক উপায়: "field one", "field two", "a ""final"" field containing two double quote marks"আমি এই পৃষ্ঠায় ট্রেভর ডিক্সনের উত্তর পরীক্ষা করে দেখিনি, তবে এটি সিএসভির আরএফসি 4180 সংজ্ঞা সম্বোধনকারী একটি উত্তর।
ডিজি

54

আরএফসি 4180 সমাধান

আরএফসি 4180 এর ফর্ম্যাটটি মেনে চলে না বলে এটি প্রশ্নের স্ট্রিং সমাধান করে না; গ্রহণযোগ্য এনকোডিংটি ডাবল উদ্ধৃতি সহ ডাবল উদ্ধৃতি থেকে পালিয়ে যাচ্ছে। নীচের সমাধানটি গুগল স্প্রেডশিট থেকে সিএসভি ফাইলের সাথে সঠিকভাবে কাজ করে।

আপডেট (3/2017)

একক লাইনের পার্সিং ভুল হবে। আরএফসি অনুসারে 4180 ফিল্ডগুলিতে সিআরএলএফ থাকতে পারে যার ফলে যে কোনও লাইন রিডার CSV ফাইলটি ভেঙে ফেলতে পারে। এখানে একটি আপডেট করা সংস্করণ যা সিএসভি স্ট্রিংকে বিশ্লেষণ করে:

'use strict';

function csvToArray(text) {
    let p = '', row = [''], ret = [row], i = 0, r = 0, s = !0, l;
    for (l of text) {
        if ('"' === l) {
            if (s && l === p) row[i] += l;
            s = !s;
        } else if (',' === l && s) l = row[++i] = '';
        else if ('\n' === l && s) {
            if ('\r' === p) row[i] = row[i].slice(0, -1);
            row = ret[++r] = [l = '']; i = 0;
        } else row[i] += l;
        p = l;
    }
    return ret;
};

let test = '"one","two with escaped """" double quotes""","three, with, commas",four with no quotes,"five with CRLF\r\n"\r\n"2nd line one","two with escaped """" double quotes""","three, with, commas",four with no quotes,"five with CRLF\r\n"';
console.log(csvToArray(test));

পুরানো উত্তর

(একক লাইন সমাধান)

function CSVtoArray(text) {
    let ret = [''], i = 0, p = '', s = true;
    for (let l in text) {
        l = text[l];
        if ('"' === l) {
            s = !s;
            if ('"' === p) {
                ret[i] += '"';
                l = '-';
            } else if ('' === p)
                l = '-';
        } else if (s && ',' === l)
            l = ret[++i] = '';
        else
            ret[i] += l;
        p = l;
    }
    return ret;
}
let test = '"one","two with escaped """" double quotes""","three, with, commas",four with no quotes,five for fun';
console.log(CSVtoArray(test));

এবং মজাদার জন্য, আপনি কীভাবে অ্যারে থেকে সিএসভি তৈরি করবেন তা এখানে:

function arrayToCSV(row) {
    for (let i in row) {
        row[i] = row[i].replace(/"/g, '""');
    }
    return '"' + row.join('","') + '"';
}

let row = [
  "one",
  "two with escaped \" double quote",
  "three, with, commas",
  "four with no quotes (now has)",
  "five for fun"
];
let text = arrayToCSV(row);
console.log(text);



7

পিইজি (.js) ব্যাকরণ যা আরএফসি 4180 উদাহরণগুলি http://en.wikedia.org/wiki/Comma-separated_values এ পরিচালনা করে :

start
  = [\n\r]* first:line rest:([\n\r]+ data:line { return data; })* [\n\r]* { rest.unshift(first); return rest; }

line
  = first:field rest:("," text:field { return text; })*
    & { return !!first || rest.length; } // ignore blank lines
    { rest.unshift(first); return rest; }

field
  = '"' text:char* '"' { return text.join(''); }
  / text:[^\n\r,]* { return text.join(''); }

char
  = '"' '"' { return '"'; }
  / [^"]

Http://jsfiddle.net/knvzk/10 বা https://pegjs.org/online এ পরীক্ষা করুন ।

উত্পন্ন পার্সারটি https://gist.github.com/3362830 এ ডাউনলোড করুন ।


6

আমার খুব সুনির্দিষ্ট ব্যবহারের কেস ছিল যেখানে আমি গুগল শীট থেকে আমার ওয়েব অ্যাপ্লিকেশনটিতে ঘর অনুলিপি করতে চেয়েছিলাম। কক্ষগুলিতে ডাবল-কোট এবং নতুন-লাইন অক্ষর অন্তর্ভুক্ত থাকতে পারে। অনুলিপি এবং পেস্ট ব্যবহার করে, কক্ষগুলি একটি ট্যাব অক্ষর দ্বারা সীমিত করা হয়, এবং বিজোড় ডেটা সহ কোষগুলি ডাবল উদ্ধৃত হয়। আমি এই মূল সমাধানটি, রিজেক্সএক্স এবং জ্যাকুরি-সিএসভি, এবং সিএসভিটিওআরرے ব্যবহার করে লিঙ্কিত নিবন্ধটি চেষ্টা করেছি। http://papaparse.com/ কেবলমাত্র বাক্সটির বাইরে কাজ করে। কপি এবং পেস্ট করা ডিফল্ট স্বতঃ-সনাক্তকরণ বিকল্পগুলির সাথে Google পত্রকগুলিতে বিজোড়।


4
এটিকে অনেক উচ্চতর স্থান দেওয়া উচিত, কখনও নিজের সিএসভি পার্সার রোল করার চেষ্টা করবেন না , এটি সঠিকভাবে কাজ করবে না - বিশেষত রেজিক্সগুলি ব্যবহার করার সময়। পাপাপারস দুর্দান্ত - এটি ব্যবহার করুন!
cbley

6

আমি ফেকরাইনব্রিগ্যান্ডের উত্তরটি পছন্দ করেছি, তবে এতে কয়েকটি সমস্যা রয়েছে: এটি একটি উদ্ধৃতি এবং কমাগুলির মধ্যে শ্বেত স্থান পরিচালনা করতে পারে না এবং টানা ২ টি কমা সমর্থন করে না। আমি তার উত্তর সম্পাদনা করার চেষ্টা করেছি কিন্তু আমার সম্পাদনা পর্যালোচকদের দ্বারা প্রত্যাখ্যাত হয়েছে যা সম্ভবত আমার কোড বুঝতে পারে নি। এখানে আমার ফেকরাইনব্রিগ্যান্ডের কোডটির সংস্করণ। একটি ফিজলও রয়েছে: http://jsfiddle.net/xTezm/46/

String.prototype.splitCSV = function() {
        var matches = this.match(/(\s*"[^"]+"\s*|\s*[^,]+|,)(?=,|$)/g);
        for (var n = 0; n < matches.length; ++n) {
            matches[n] = matches[n].trim();
            if (matches[n] == ',') matches[n] = '';
        }
        if (this[0] == ',') matches.unshift("");
        return matches;
}

var string = ',"string, duppi, du" , 23 ,,, "string, duppi, du",dup,"", , lala';
var parsed = string.splitCSV();
alert(parsed.join('|'));

4

লোকেরা এটির জন্য রেজিএক্সের বিপক্ষে ছিল বলে মনে হয়েছিল। কেন?

(\s*'[^']+'|\s*[^,]+)(?=,|$)

এখানে কোড। আমিও এক ঝাঁকুনি বানিয়েছি ।

String.prototype.splitCSV = function(sep) {
  var regex = /(\s*'[^']+'|\s*[^,]+)(?=,|$)/g;
  return matches = this.match(regex);    
}

var string = "'string, duppi, du', 23, 'string, duppi, du', lala";
var parsed = string.splitCSV();
alert(parsed.join('|'));

4
হুম, আপনার রিজেপ্সে কিছু সমস্যা রয়েছে: এটি কোট এবং কমাগুলির মধ্যে শ্বেতস্পেস পরিচালনা করতে পারে না এবং টানা ২ টি কমা সমর্থন করে না। আমি আপনার উত্তরটি কোডের সাথে আপডেট করেছি যা উভয় সমস্যার সমাধান করে এবং একটি নতুন ফিডাল
হামারএনএল

কোনও কারণে আপনার কোডে আমার সম্পাদনা প্রত্যাখ্যান করা হয়েছিল কারণ এটি "পোস্টের মূল উদ্দেশ্য থেকে বিচ্যুত হবে"। খুব অদ্ভুত!? আমি আপনার কোডটি নিয়েছি এবং এটির সাথে দুটি সমস্যার সমাধান করেছি। কীভাবে সেই পোস্টের উদ্দেশ্য বদলে যায় !? যাইহোক ... আমি কেবল এই প্রশ্নের একটি নতুন উত্তর যুক্ত করেছি।
হামারএনএল

আপনার উত্তরে ভাল প্রশ্ন, @ ফেকরাইনব্রিগ্যান্ড। আমি একজন সবার জন্য রেইজেক্সের জন্য এবং তার কারণে আমি স্বীকার করি যে এটি কাজের জন্য ভুল সরঞ্জাম tool
nyer

4
আমার মেয়াদ শেষ না হওয়া এখানে খুব খারাপ। আমি প্রতিজ্ঞা করছি আমি উপর গত 6 বছর :-p ভাল অর্জিত করেছি
রাহাজান

4

তালিকায় আরও একটি যুক্ত করা, কারণ আমি উপরের সমস্তটি যথেষ্ট "KISS" যথেষ্ট পরিমাণে খুঁজে পাই না।

উদ্ধৃত আইটেমগুলি এড়িয়ে গিয়ে কমা বা নিউলাইনগুলি সন্ধান করতে এটি একটিকে রেজিक्स ব্যবহার করে। আশা করি এটি এমনই কিছু যা কুকুরছানা তাদের নিজেরাই পড়তে পারে। splitFinderRegexp তিনটি জিনিস এটা (ক দ্বারা বিভক্ত করে হয়েছে |):

  1. , - কমা খুঁজে
  2. \r?\n - নতুন রেখাগুলি সন্ধান করে, (রফতানিকারকটি ভাল হলে সম্ভাব্য বাহন ফেরত দিয়ে)
  3. "(\\"|[^"])*?"- উদ্ধৃতিতে ঘেরাও যে কোনও কিছু এড়িয়ে চলুন, কারণ কমা এবং নিউলাইনগুলি এতে কিছু যায় আসে না। \\"উদ্ধৃত আইটেমটিতে যদি একটি পালানো উক্তি থাকে তবে শেষের উদ্ধৃতিটি পাওয়া যাওয়ার আগে এটি ধরা পড়বে।

const splitFinder = /,|\r?\n|"(\\"|[^"])*?"/g;

function csvTo2dArray(parseMe) {
  let currentRow = [];
  const rowsOut = [currentRow];
  let lastIndex = splitFinder.lastIndex = 0;
  
  // add text from lastIndex to before a found newline or comma
  const pushCell = (endIndex) => {
    endIndex = endIndex || parseMe.length;
    const addMe = parseMe.substring(lastIndex, endIndex);
    // remove quotes around the item
    currentRow.push(addMe.replace(/^"|"$/g, ""));
    lastIndex = splitFinder.lastIndex;
  }


  let regexResp;
  // for each regexp match (either comma, newline, or quoted item)
  while (regexResp = splitFinder.exec(parseMe)) {
    const split = regexResp[0];

    // if it's not a quote capture, add an item to the current row
    // (quote captures will be pushed by the newline or comma following)
    if (split.startsWith(`"`) === false) {
      const splitStartIndex = splitFinder.lastIndex - split.length;
      pushCell(splitStartIndex);

      // then start a new row if newline
      const isNewLine = /^\r?\n$/.test(split);
      if (isNewLine) { rowsOut.push(currentRow = []); }
    }
  }
  // make sure to add the trailing text (no commas or newlines after)
  pushCell();
  return rowsOut;
}

const rawCsv = `a,b,c\n"test\r\n","comma, test","\r\n",",",\nsecond,row,ends,with,empty\n"quote\"test"`
const rows = csvTo2dArray(rawCsv);
console.log(rows);


যদি আমি ফাইলআরডিডার এবং আমার ফলাফলের মাধ্যমে আমার ফাইলটি পড়ি: Id, Name, Age 1, John Smith, 65 2, Jane Doe, 30 আমি যে কলামগুলি নির্দিষ্ট করেছি তার উপর ভিত্তি করে পার্স করতে পারি?
নীলপল্ল

আপনি 2 ডি অ্যারে পাওয়ার পরে, প্রথম সূচকটি মুছে ফেলুন (এটি আপনার প্রপ নামগুলি), তারপরে বাকী অ্যারেতে পুনরাবৃত্তি করুন এবং সম্পত্তি হিসাবে প্রতিটি মানের সাথে অবজেক্ট তৈরি করুন। এটি দেখতে এটির মতো লাগবে:[{Id: 1, Name: "John Smith", Age: 65}, {Id: 2, Name: "Jane Doe", Age: 30}]
সেফ রিড

3

যদি আপনার উদ্ধৃতি ডিলিমিটারটি ডাবল কোট হতে পারে তবে এটি CSV ডেটা পার্স করার জন্য উদাহরণ জাভাস্ক্রিপ্ট কোডের একটি সদৃশ ।

আপনি প্রথমে ডাবল-কোটগুলিতে সমস্ত একক উদ্ধৃতি অনুবাদ করতে পারেন:

string = string.replace( /'/g, '"' );

... বা আপনি ডাবল-কোটের পরিবর্তে একক-কোটগুলি সনাক্ত করতে এই প্রশ্নে রেজেক্স সম্পাদনা করতে পারেন:

// Quoted fields.
"(?:'([^']*(?:''[^']*)*)'|" +

তবে এটি নির্দিষ্ট মার্কআপ ধরেছে যা আপনার প্রশ্ন থেকে পরিষ্কার নয়। আপনার প্রশ্নের উপর আমার মন্তব্য অনুযায়ী মার্কআপের সমস্ত বিভিন্ন সম্ভাবনাগুলি কী হতে পারে তা দয়া করে পরিষ্কার করে দিন।


2

আমার উত্তর অনুমান করে যে আপনার ইনপুটটি ওয়েব উত্সগুলি থেকে কোড / সামগ্রীর প্রতিচ্ছবি যেখানে একক এবং ডাবল উদ্ধৃতি অক্ষরগুলি সম্পূর্ণরূপে বিনিময়যোগ্য হয় যদি তারা অ-পালানো মিলের সেট হিসাবে দেখা দেয়।

আপনি এটির জন্য রেজেক্স ব্যবহার করতে পারবেন না। আপনি যে স্ট্রিংটি বিভক্ত করতে চান তা বিশ্লেষণ করতে আপনাকে আসলে একটি মাইক্রো পার্সার লিখতে হবে। আমি, এই উত্তরের জন্য, আপনার স্ট্রিংয়ের উদ্ধৃত অংশগুলিকে সাব-স্ট্রিং হিসাবে কল করব। আপনার বিশেষভাবে স্ট্রিং জুড়ে চলতে হবে। নিম্নলিখিত বিষয় বিবেচনা করুন:

var a = "some sample string with \"double quotes\" and 'single quotes' and some craziness like this: \\\" or \\'",
    b = "sample of code from JavaScript with a regex containing a comma /\,/ that should probably be ignored.";

এই ক্ষেত্রে আপনার কোনও ধারণা নেই যেখানে কেবল একটি চরিত্র নিদর্শনটির জন্য ইনপুট বিশ্লেষণ করে একটি উপ-স্ট্রিং শুরু হয় বা শেষ হয়। পরিবর্তে আপনাকে কোনও উদ্ধৃতি চরিত্রের একটি উদ্ধৃতি চরিত্র ব্যবহৃত হয় কিনা তা নিজেই অব্যক্ত, এবং উদ্ধৃতি চরিত্রটি পালানোর অনুসরণ করছে না সে বিষয়ে সিদ্ধান্ত নিতে যুক্তি রচনা করতে হবে।

আমি আপনার জন্য কোডের জটিলতার সেই স্তরটি লিখতে যাচ্ছি না, তবে আপনি সম্প্রতি যা লিখেছিলেন তার দিকে নজর দিতে পারেন যা আপনার প্রয়োজনীয় প্যাটার্নটি রয়েছে। এই কোডটি কমা দিয়ে কিছুই করার নেই, তবে অন্যথায় আপনার নিজের কোড লেখার জন্য আপনাকে অনুসরণ করার জন্য এটি বৈধ যথেষ্ট মাইক্রো পার্সার। নিম্নলিখিত অ্যাপ্লিকেশনটির asifix ফাংশনটি দেখুন:

https://github.com/austincheney/Pretty-Diff/blob/master/fulljsmin.js


2

এই উত্তর পরিপূরক

আপনার যদি উদ্ধৃতিগুলি বিশ্লেষণের দরকার হয় তবে অন্য একটি উদ্ধৃতি সহ পালিয়ে গেছে, উদাহরণস্বরূপ:

"some ""value"" that is on xlsx file",123

তুমি ব্যবহার করতে পার

function parse(text) {
  const csvExp = /(?!\s*$)\s*(?:'([^'\\]*(?:\\[\S\s][^'\\]*)*)'|"([^"\\]*(?:\\[\S\s][^"\\]*)*)"|"([^""]*(?:"[\S\s][^""]*)*)"|([^,'"\s\\]*(?:\s+[^,'"\s\\]+)*))\s*(?:,|$)/g;

  const values = [];

  text.replace(csvExp, (m0, m1, m2, m3, m4) => {
    if (m1 !== undefined) {
      values.push(m1.replace(/\\'/g, "'"));
    }
    else if (m2 !== undefined) {
      values.push(m2.replace(/\\"/g, '"'));
    }
    else if (m3 !== undefined) {
      values.push(m3.replace(/""/g, '"'));
    }
    else if (m4 !== undefined) {
      values.push(m4);
    }
    return '';
  });

  if (/,\s*$/.test(text)) {
    values.push('');
  }

  return values;
}

আমি দেখতে পেয়েছি যে এটি এখনও "jjj "" kkk""","123"
পার্সিংয়ে

2

স্ট্রিংয়ে সিএসভি ফাইলটি পড়ার সময় এতে স্ট্রিংয়ের মাঝে নাল মান রয়েছে, সুতরাং এটি লাইন দিয়ে \ 0 লাইন দিয়ে চেষ্টা করুন । এটা আমার জন্য কাজ করে.

stringLine = stringLine.replace(/\0/g, "" );

2

আমাকে যখন কোনও সিএসভি ফাইল বিশ্লেষণ করতে হয়েছিল তখন আমি একই ধরণের সমস্যার মুখোমুখি হয়েছি।

ফাইলটিতে একটি কলামের ঠিকানা রয়েছে যা ',' রয়েছে।

সেই সিএসভি ফাইলটি জেএসএনে পার্স করার পরে, কীগুলি জেএসএন ফাইলে রূপান্তর করার সময় আমি কীগুলির মেলানো ম্যাপিং পাচ্ছি।

আমি ফাইলটি পার্সিংয়ের জন্য নোড.জেএস এবং বেবি পার্স এবং সিএসভিটোজসনের মতো লাইব্রেরি ব্যবহার করেছি

ফাইলের উদাহরণ -

address,pincode
foo,baar , 123456

আমি যখন জেএসএন-এ বেবি পার্স ব্যবহার না করে সরাসরি পার্সিং করছিলাম, তখন আমি পেয়েছিলাম:

[{
 address: 'foo',
 pincode: 'baar',
 'field3': '123456'
}]

সুতরাং আমি কোড লিখেছি যা প্রতিটি ক্ষেত্রের সাথে অন্য কোনও সীমানার সহ কমা (,) সরিয়ে দেয়:

/*
 csvString(input) = "address, pincode\\nfoo, bar, 123456\\n"
 output = "address, pincode\\nfoo {YOUR DELIMITER} bar, 123455\\n"
*/
const removeComma = function(csvString){
    let delimiter = '|'
    let Baby = require('babyparse')
    let arrRow = Baby.parse(csvString).data;
    /*
      arrRow = [
      [ 'address', 'pincode' ],
      [ 'foo, bar', '123456']
      ]
    */
    return arrRow.map((singleRow, index) => {
        //the data will include
        /*
        singleRow = [ 'address', 'pincode' ]
        */
        return singleRow.map(singleField => {
            //for removing the comma in the feild
            return singleField.split(',').join(delimiter)
        })
    }).reduce((acc, value, key) => {
        acc = acc +(Array.isArray(value) ?
         value.reduce((acc1, val)=> {
            acc1 = acc1+ val + ','
            return acc1
        }, '') : '') + '\n';
        return acc;
    },'')
}

ফিরিয়ে দেওয়া ফাংশনটি সিএসভিটোজসন লাইব্রেরিতে পাঠানো যেতে পারে এবং ফলস্বরূপ ব্যবহার করা যেতে পারে।

const csv = require('csvtojson')

let csvString = "address, pincode\\nfoo, bar, 123456\\n"
let jsonArray = []
modifiedCsvString = removeComma(csvString)
csv()
  .fromString(modifiedCsvString)
  .on('json', json => jsonArray.push(json))
  .on('end', () => {
    /* do any thing with the json Array */
  })

এখন আপনি যেমন আউটপুট পেতে পারেন:

[{
  address: 'foo, bar',
  pincode: 123456
}]

2

কোনও রেজিপ্সপ, পঠনযোগ্য নয় এবং https://en.wikedia.org/wiki/Comma-separated_values# বেসিক_রুলস অনুসারে :

function csv2arr(str: string) {
    let line = ["",];
    const ret = [line,];
    let quote = false;

    for (let i = 0; i < str.length; i++) {
        const cur = str[i];
        const next = str[i + 1];

        if (!quote) {
            const cellIsEmpty = line[line.length - 1].length === 0;
            if (cur === '"' && cellIsEmpty) quote = true;
            else if (cur === ",") line.push("");
            else if (cur === "\r" && next === "\n") { line = ["",]; ret.push(line); i++; }
            else if (cur === "\n" || cur === "\r") { line = ["",]; ret.push(line); }
            else line[line.length - 1] += cur;
        } else {
            if (cur === '"' && next === '"') { line[line.length - 1] += cur; i++; }
            else if (cur === '"') quote = false;
            else line[line.length - 1] += cur;
        }
    }
    return ret;
}

1

এই ব্লগ পোস্ট অনুসারে , এই ফাংশনটি এটি করা উচিত:

String.prototype.splitCSV = function(sep) {
  for (var foo = this.split(sep = sep || ","), x = foo.length - 1, tl; x >= 0; x--) {
    if (foo[x].replace(/'\s+$/, "'").charAt(foo[x].length - 1) == "'") {
      if ((tl = foo[x].replace(/^\s+'/, "'")).length > 1 && tl.charAt(0) == "'") {
        foo[x] = foo[x].replace(/^\s*'|'\s*$/g, '').replace(/''/g, "'");
      } else if (x) {
        foo.splice(x - 1, 2, [foo[x - 1], foo[x]].join(sep));
      } else foo = foo.shift().split(sep).concat(foo);
    } else foo[x].replace(/''/g, "'");
  } return foo;
};

আপনি এটিকে এভাবে ডাকবেন:

var string = "'string, duppi, du', 23, lala";
var parsed = string.splitCSV();
alert(parsed.join("|"));

এই jsfiddle ধরণের কাজ করে, তবে দেখে মনে হচ্ছে কিছু উপাদানগুলির সামনে তাদের স্পেস রয়েছে।


একটি রেজেক্সে সমস্ত করার আছে তা কল্পনা। এই কারণেই রেজেক্সগুলি কখনও কখনও পার্সিংয়ের জন্য উপযুক্ত হয় না।
CanSpice

এই সমাধানটি সহজভাবে কাজ করে না। মূল পরীক্ষার স্ট্রিং দেওয়া: "'string, duppi, du', 23, lala"এই ফাংশনটি ফিরে আসে:["'string"," duppi"," du'"," 23"," lala"]
রডগারুনার

@ রিডারজার্নার: ঠিক আছে তুমি। ফাংশনটি ঠিক করার জন্য আমি উত্তর এবং jsfiddle সম্পাদনা করেছি। মূলত, আমি সুইচ "'"করতে '"'এবং ভাইস বিপরীতভাবে।
CanSpice

এটি সাহায্য করেছে, তবে এখন ফাংশনটি একক উদ্ধৃত সিএসভি স্ট্রিংগুলিতে ডাবল উদ্ধৃত মানগুলিকে ভুলভাবে পরিচালনা করে। উদাহরণস্বরূপ মূল পরীক্ষার স্ট্রিংয়ের উদ্ধৃতি প্রকারগুলি '"string, duppi, du", 23, lala'['"string',' duppi'.' du"',' 23',' lala']
বিপরীত করা

@ ক্যানস্পাইস, আপনার মন্তব্য আমাকে রেজিএক্স দিয়ে চেষ্টা করতে অনুপ্রাণিত করেছিল। এটিতে বেশ কয়েকটি বৈশিষ্ট্য নেই তবে এগুলি সহজেই যুক্ত করা যেতে পারে। (আপনি যদি আগ্রহী হন তবে আমার উত্তর এই পৃষ্ঠায় রয়েছে))
ব্রিগেন্ড

0

নিয়মিত অভিব্যক্তি উদ্ধার! এই কয়েকটি লাইনের কোড হ্যান্ডেলগুলি এমবেডেড কমা, কোটস এবং আরএফসি 4180 মানক ভিত্তিতে নতুন লাইনের সাথে সঠিকভাবে উদ্ধৃত ক্ষেত্রগুলি রয়েছে।

function parseCsv(data, fieldSep, newLine) {
    fieldSep = fieldSep || ',';
    newLine = newLine || '\n';
    var nSep = '\x1D';
    var qSep = '\x1E';
    var cSep = '\x1F';
    var nSepRe = new RegExp(nSep, 'g');
    var qSepRe = new RegExp(qSep, 'g');
    var cSepRe = new RegExp(cSep, 'g');
    var fieldRe = new RegExp('(?<=(^|[' + fieldSep + '\\n]))"(|[\\s\\S]+?(?<![^"]"))"(?=($|[' + fieldSep + '\\n]))', 'g');
    var grid = [];
    data.replace(/\r/g, '').replace(/\n+$/, '').replace(fieldRe, function(match, p1, p2) {
        return p2.replace(/\n/g, nSep).replace(/""/g, qSep).replace(/,/g, cSep);
    }).split(/\n/).forEach(function(line) {
        var row = line.split(fieldSep).map(function(cell) {
            return cell.replace(nSepRe, newLine).replace(qSepRe, '"').replace(cSepRe, ',');
        });
        grid.push(row);
    });
    return grid;
}

const csv = 'A1,B1,C1\n"A ""2""","B, 2","C\n2"';
const separator = ',';      // field separator, default: ','
const newline = ' <br /> '; // newline representation in case a field contains newlines, default: '\n' 
var grid = parseCsv(csv, separator, newline);
// expected: [ [ 'A1', 'B1', 'C1' ], [ 'A "2"', 'B, 2', 'C <br /> 2' ] ]

অন্য কোথাও বলা না থাকলে আপনার কোনও সসীম রাষ্ট্র মেশিনের দরকার নেই। নিয়মিত অভিব্যক্তিটি আরএফসি 4180 কে সঠিকভাবে ধনাত্মক চেহারা, নেতিবাচক লুকবিহীন এবং ইতিবাচক চেহারাটির জন্য ধন্যবাদ হ্যান্ডেল করে।

ক্লোন / ডাউনলোড কোডটি https://github.com/peterthoeny/parse-csv-js এ


0

পাশাপাশি চমৎকার এবং সম্পূর্ণ রাইডারওয়ানারের উত্তরকে বাদ দিয়ে আমি যখন আপনার ব্যাকএন্ড পিএইচপি চালায় তখন একটি খুব সাধারণ কাজের কথা ভাবলাম।

এই পিএইচপি ফাইলটি আপনার ডোমেনের ব্যাকএন্ডে যুক্ত করুন (বলুন csv.php)

<?php
    session_start(); // Optional
    header("content-type: text/xml");
    header("charset=UTF-8");
    // Set the delimiter and the End of Line character of your CSV content:
    echo json_encode(array_map('str_getcsv', str_getcsv($_POST["csv"], "\n")));
?>

এখন আপনার জাভাস্ক্রিপ্ট টুলকিটে এই ফাংশনটি যুক্ত করুন (আমার বিশ্বাস ক্রসব্রোজার তৈরি করতে কিছুটা সংশোধন করা উচিত)।

function csvToArray(csv) {
    var oXhr = new XMLHttpRequest;
    oXhr.addEventListener("readystatechange",
        function () {
            if (this.readyState == 4 && this.status == 200) {
                console.log(this.responseText);
                console.log(JSON.parse(this.responseText));
            }
        }
    );
    oXhr.open("POST","path/to/csv.php",true);
    oXhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded; charset=utf-8");
    oXhr.send("csv=" + encodeURIComponent(csv));
}

এটির জন্য আপনাকে একটি আজাক্স কল দিতে হবে, তবে কমপক্ষে আপনি কোডটি নকল করবেন না বা কোনও বাহ্যিক গ্রন্থাগারও অন্তর্ভুক্ত করবেন না।

তথ্যসূত্র: http://php.net/manual/en/function.str-getcsv.php


0

আপনি নীচের উদাহরণের মতো পাপ্পার্স.জে ব্যবহার করতে পারেন :

<!DOCTYPE html>
<html lang="en">

    <head>
        <title>CSV</title>
    </head>

    <body>
        <input type="file" id="files" multiple="">
        <button onclick="csvGetter()">CSV Getter</button>
        <h3>The Result will be in the Console.</h3>

        <script src="papaparse.min.js"></script>

        <script>
            function csvGetter() {

                var file = document.getElementById('files').files[0];
                Papa.parse(file, {
                    complete: function(results) {
                        console.log(results.data);
                    }
                });
            }
          </script>
    </body>

</html>

একই ফোল্ডারে papaparse.js অন্তর্ভুক্ত করতে ভুলবেন না।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.