Как да направите регулярен израз "не съдържа".

Имам малък проблем при създаването на обикновен експресин. Очакван вход:

blahblahblah, blahblahblah, 'blahblahblah', "blahblahblah, asdfd"

Трябва да получа думи, разделени със запетая, за да подредя. Но не мога да използвам функцията за разделяне, защото запетая може да се появи и в низове. И така, очакваният резултат е:

arr[0] = blahblahblah
arr[1] = blahblahblah
arr[2] = 'blahblahblah'
arr[3] = "blahblahblah, asdfd"

Някой знае ли някакъв регулярен израз или някакво друго решение, което може да ми помогне и да ми даде подобен изход? Моля помогнете.


person user35443    schedule 04.04.2012    source източник
comment
Просто трябва да получа думи от входа, разделени със запетая.   -  person user35443    schedule 04.04.2012
comment
изглежда подозрително като CSV формат.   -  person Jodrell    schedule 04.04.2012
comment
Да, трябват ми стойности, разделени със запетая.   -  person user35443    schedule 04.04.2012
comment
освен когато запетаята се съдържа в двойни кавички, но какво да кажем за двойни кавички в двойни кавички, това позволено ли е?   -  person Jodrell    schedule 04.04.2012
comment
И така, това всъщност някакъв ред от CSV ли е или този проблем е ограничен точно до вашия пример и само псевдо CSV?   -  person Jodrell    schedule 04.04.2012
comment
CSV не поддържа 'blahblah', само blahblah или "blahblah"   -  person Ωmega    schedule 04.04.2012
comment
Как искате да обработвате низове като "First "" item", тъй като от CSV това е един низ, защото "" се преобразува в " вътре в елемента на низа...   -  person Ωmega    schedule 04.04.2012
comment
Това е обрат на класическия XY проблем. Вашият действителен проблем е как да разделите въвеждането със запетаи, с изключение на тези в кавички. Заглавието на вашия въпрос не споменава действителния ви проблем! Това намалява вероятността да получите помощта, от която се нуждаете. Ограничавате набора от отговарящи до хора, които се интересуват достатъчно от проблем Y, за да прочетат по-нататък, и знаят достатъчно за проблем X, за да дадат добро решение.   -  person Kevin    schedule 04.04.2012
comment
Не сте сигурни как искате да се справите с интервалите между елементите и новите редове...   -  person Ωmega    schedule 04.04.2012
comment
Предлагам ви да конвертирате входа в CSV стандарт и след това да използвате някаква техника за такъв стандарт...   -  person Ωmega    schedule 04.04.2012


Отговори (4)


Бихте могли да направите нещо подобно, предвид ограничения проблем. Regex е по-кратък и вероятно по-прост.

string line = <YourLine>
var result = new StringBuilder();
var inQuotes = false;

foreach(char c in line)
{
    switch (c)
    {
        case '"':
            result.Append()
            inQuotes = !inQuotes;
            break;

        case ',':
            if (!inQuotes)
            {
                yield return result.ToString();
                result.Clear();
            }

        default:
            result.Append()
            break;                
    }
}
person Jodrell    schedule 04.04.2012
comment
user35443 иска също поддръжка на ', а не само на ", дори това да не е стандартно поведение... - person Ωmega; 04.04.2012
comment
@user35443 - Тогава трябва да редактирате въпроса си, защото приехте отговор, който не е въпросът, за който се иска... И SO е тук и за други читатели, така че не ги обърквайте. - person Ωmega; 04.04.2012
comment
Не се препоръчва използването на yield return и пропускащи случайни блокове. Въпреки това концепцията ми харесва. Бързо и лесно за разбиране. Също така: @stackoverflow: Проста корекция. - person Mooing Duck; 04.04.2012
comment
@MooingDuck - Исках да редактирам въпрос, а не отговор. Вашата редакция прави кода безполезен, тъй като сега ще съответства на "one', 'two" като два елемента! - person Ωmega; 04.04.2012
comment
@stackoverflow: А, не съм мислил за влагане. Върнах редакцията назад, това е много по-съществена редакция, отколкото си мислех. - person Mooing Duck; 04.04.2012

Не съм сигурен, че това е най-оптималното, но даде правилния резултат от вашия тестов случай на http://derekslager.com/blog/posts/2007/09/a-better-dotnet-regular-expression-tester.ashx:

(?>"[^"]*")|(?>'[^']*')|(?>[^,\s]+)

C# низова версия:

@"(?>""[^""]*"")|(?>'[^']*')|(?>[^,\s]+)"
person FishBasketGordo    schedule 04.04.2012
comment
Няма да работи за "first "" item", "Second Item", Third - person Ωmega; 04.04.2012
comment
@stackoverflow - Да, и не го очаквах. Това изисква низовете в кавички да не съдържат подобни кавички. Както казах, той произвежда правилния изход за дадения (ограничен) тестов случай. - person FishBasketGordo; 04.04.2012
comment
@FishBasketGordo - вашият код работи за ограничена спецификация, което user35443 поиска... - person Ωmega; 04.04.2012

Един възможен подход е да се раздели със запетаи (като се използва string.Split, а не RegEx) и след това да се повторят резултатите. За всеки резултат, който съдържа 0 или 2 ' или " знака, добавете го към нов списък. Когато даден резултат съдържа 1 ' или ", съединете отново следващите елементи (добавете запетая), докато резултатът има 2 ' или ", след което добавете това към новия списък.

person Jay    schedule 04.04.2012
comment
О, това е просто решение. - person Mooing Duck; 04.04.2012
comment
@MooingDuck - сериозно ли? - person Ωmega; 04.04.2012
comment
@stackoverflow: Това не е най-бързият или най-елегантният отговор, но е много лесен за разбиране и дава правилните резултати. Не мога да потвърдя останалите отговори, защото тези регулярни изрази са извън мен. Това и това на Джодрел са единствените предложения, които аз мога да направя. - person Mooing Duck; 04.04.2012

Вместо да пускате свой собствен CSV анализатор, обмислете използването на стандартния готов клас TextFieldParser, който се доставя с .NET Framework.

Или като алтернатива използвайте Microsoft Ace и OleDbDataReader за директно четене файловете чрез ADO.NET. Пример може да бъде намерен в редица други публикации, като тази. И има тази по-стара публикация на CodeProject, който можете да използвате като пример. Просто се уверете, че препращате към най-новия драйвер на Ace вместо стария драйвер Jet.OLEDB.4.0

Тези опции са много по-лесни за поддържане в дългосрочен план, отколкото който и да е персонализиран анализатор на файлове. И те вече знаят как да се справят с многото ъглови случаи, които обграждат не толкова добре документирания CSV формат.

person jessehouwing    schedule 04.04.2012