سؤال

أعلم أن لدي مشكلتين الآن.لكني أستمتع!

لقد بدأت مع هذه النصيحة ليس لمحاولة الانقسام، ولكن بدلاً من ذلك للتوافق مع ما هو حقل مقبول، وتوسيعه من هناك إلى هذا التعبير.

final Pattern pattern = Pattern.compile("\"([^\"]*)\"|(?<=,|^)([^,]*)(?=,|$)");

يبدو التعبير هكذا بدون علامات الاقتباس المزعجة:

"([^"]*)"|(?<=,|^)([^,]*)(?=,|$)

هذا يعمل بشكل جيد بالنسبة لي - إما أنه يتطابق مع "علامتي اقتباس وما بينهما"، أو "شيء بين بداية السطر أو الفاصلة ونهاية السطر أو الفاصلة".التكرار خلال التطابقات يجعلني أحصل على جميع الحقول، حتى لو كانت فارغة.على سبيل المثال،

the quick, "brown, fox jumps", over, "the",,"lazy dog"

ينقسم الى

the quick
"brown, fox jumps"
over
"the"

"lazy dog"

عظيم!الآن أريد إسقاط علامات الاقتباس، لذلك أضفت مجموعات البحث للأمام والخلف كما كنت أفعل مع الفواصل.

final Pattern pattern = Pattern.compile("(?<=\")([^\"]*)(?=\")|(?<=,|^)([^,]*)(?=,|$)");

مرة أخرى التعبير هو:

(?<=")([^"]*)(?=")|(?<=,|^)([^,]*)(?=,|$)

بدلا من النتيجة المرجوة

the quick
brown, fox jumps
over
the

lazy dog

الآن أحصل على هذا التقسيم:

the quick
"brown
 fox jumps"
,over,
"the"
,,
"lazy dog"

ماذا ينقصني؟

هل كانت مفيدة؟

المحلول

أسبقية المشغل.في الأساس لا يوجد شيء.كل شيء من اليسار إلى اليمين.لذلك يتم تطبيق أو (|) على علامة الاقتباس الختامية والنظرة الأمامية للفاصلة

يحاول:

(?:(?<=")([^"]*)(?="))|(?<=,|^)([^,]*)(?=,|$)

نصائح أخرى

(?:^|,)\s*(?:(?:(?=")"([^"].*?)")|(?:(?!")(.*?)))(?=,|$)

هذا يجب أن يفعل ما تريد.

توضيح:

(?:^|,)\s*

يجب أن يبدأ النمط بـ أو بداية السلسلة.أيضًا، تجاهل كل المسافات البيضاء في البداية.

انظر للأمام وانظر ما إذا كان الباقي يبدأ باقتباس

(?:(?=")"([^"].*?)")

إذا كان الأمر كذلك، فقم بمطابقة غير جشع حتى الاقتباس التالي.

(?:(?!")(.*?))

إذا لم يبدأ بعلامة اقتباس، فقم بمطابقتها بشكل غير جشع حتى الفاصلة التالية أو نهاية السلسلة.

(?=,|$)

يجب أن ينتهي النمط بفاصلة أو نهاية السلسلة.

عندما بدأت أفهم الخطأ الذي ارتكبته، بدأت أيضًا أفهم مدى تعقيد عمليات البحث حولها.أدركت أخيرًا أنني لا أريد كل النص المطابق، بل أردت مجموعات محددة بداخله.انتهى بي الأمر باستخدام شيء مشابه جدًا لـ RegEx الأصلي الخاص بي باستثناء أنني لم أقم بإلقاء نظرة مسبقة على فاصلة الإغلاق، والتي أعتقد أنها يجب أن تكون أكثر كفاءة قليلاً.هنا هو الكود النهائي الخاص بي.

package regex.parser;

import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class CSVParser {

    /*
     * This Pattern will match on either quoted text or text between commas, including
     * whitespace, and accounting for beginning and end of line.
     */
    private final Pattern csvPattern = Pattern.compile("\"([^\"]*)\"|(?<=,|^)([^,]*)(?:,|$)");  
    private ArrayList<String> allMatches = null;    
    private Matcher matcher = null;
    private String match = null;
    private int size;

    public CSVParser() {        
        allMatches = new ArrayList<String>();
        matcher = null;
        match = null;
    }

    public String[] parse(String csvLine) {
        matcher = csvPattern.matcher(csvLine);
        allMatches.clear();
        String match;
        while (matcher.find()) {
            match = matcher.group(1);
            if (match!=null) {
                allMatches.add(match);
            }
            else {
                allMatches.add(matcher.group(2));
            }
        }

        size = allMatches.size();       
        if (size > 0) {
            return allMatches.toArray(new String[size]);
        }
        else {
            return new String[0];
        }           
    }   

    public static void main(String[] args) {        
        String lineinput = "the quick,\"brown, fox jumps\",over,\"the\",,\"lazy dog\"";

        CSVParser myCSV = new CSVParser();
        System.out.println("Testing CSVParser with: \n " + lineinput);
        for (String s : myCSV.parse(lineinput)) {
            System.out.println(s);
        }
    }

}

أعلم أن هذا ليس ما يريده OP، ولكن بالنسبة للقراء الآخرين، يمكن استخدام إحدى طرق String.replace لتجريد علامات الاقتباس من كل عنصر في مصفوفة النتائج الخاصة بالتعبير العادي الحالي لـ OPs.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top