Попытка проанализировать запись имени vCard с помощью Regex

У меня есть следующее регулярное выражение для анализа vCard: (VB)

        Dim options As New RegexOptions()
        options = RegexOptions.IgnoreCase Or RegexOptions.Multiline Or RegexOptions.IgnorePatternWhitespace
        regex = New Regex("(?<strElement>(N)) (;[^:]*)? (;CHARSET=UTF-8)? (:(?<strSurname>([^;\n\r]*))) (;(?<strGivenName>([^;\n\r]*)))? (;(?<strMidName>([^;\n\r]*)))? (;(?<strPrefix>([^;\n\r]*)))? (;(?<strSuffix>[^;\n\r]*))?", options)
        m = regex.Match(s)
        If m.Success Then
            Surname = m.Groups("strSurname").Value
            GivenName = m.Groups("strGivenName").Value
            MiddleName = m.Groups("strMidName").Value
            Prefix = m.Groups("strPrefix").Value
            Suffix = m.Groups("strSuffix").Value
        End If

Это работает, когда у меня есть визитная карточка, например:

BEGIN:VCARD
VERSION:2.1
N:Bacon;Kevin;Francis;Mr.;Jr.
FN: Mr. Kevin Francis Bacon Jr.
ORG:Movies.com

Но это не работает правильно, когда vCard выглядит так:

BEGIN:VCARD
VERSION:2.1
N:Bacon;Kevin
FN:Kevin Bacon
ORG:Movies.com

Регулярное выражение назначает ‹strSuffix› Кевину, а не ‹strGivenName›, как я хотел. Как я могу это исправить?

Адаптированное регулярное выражение взято отсюда: регулярное выражение vCard


person javisrk    schedule 16.11.2012    source источник
comment
Кроме того, мне интересно, как это может работать даже с вводом первого примера. Почему бы ему не соответствовать N:VCARD? Или N:2.1? Или N: Mr. Kevin Francis Bacon Jr.? (Ну, на самом деле только первые два нечетны, так как вы возвращаете только первое совпадение)   -  person Martin Ender    schedule 16.11.2012
comment
Еще один: почему вы хотите, чтобы Bacon был назначен на <strGivenName>? Вы имели в виду Kevin? Вы имели в виду <strSurname>?   -  person Martin Ender    schedule 16.11.2012
comment
Я добавил RegexOptions к своему первоначальному вопросу и имел в виду Кевина как ‹strGivenName›. Извините за путаницу.   -  person javisrk    schedule 16.11.2012
comment
IgnorePATTERNwhitepace предназначен только для комментирования шаблонов, а не для процесса регулярных выражений. В вашем шаблоне нет комментариев, и он не занимает несколько строк; поэтому удалите эту опцию.   -  person ΩmegaMan    schedule 17.11.2012


Ответы (2)


Вы должны быть хороши с шаблоном регулярных выражений

^N(?:;(?!CHARSET=UTF-8)[^:]*|)(?:;CHARSET=UTF-8|):(?<strSurname>[^;\n\r]*);?(?<strGivenName>[^;\n\r]*);?(?<strMidName>[^;\n\r]*);?(?<strPrefix>[^;\n\r]*);?(?<strSuffix>[^;\n\r]*)

См. этот пример и в этом примере.

person Ωmega    schedule 16.11.2012

Я бы не стал анализировать каждую строку уникальным регулярным выражением, а вместо этого токенизировал каждую строку. Затем пусть полученный процесс определит, есть ли недостающие (необязательные) элементы. Вот шаблон, который просто размечает каждую строку по ее коду и элементам данных (используйте явный захват и многострочный).

^(?<Code>[^:]+)(:)((?<Tokens>[^;\r\n]+)(;?))+

Это ставит акцент на создании отдельных объектов кода, которые обрабатывают бизнес-логику, независимо от того, отсутствуют данные или нет. Сбои больше не являются сбоями регулярных выражений, а сбоями постобработки бизнес-логики, которые, ИМХО, лучше отлаживать и поддерживать.

person ΩmegaMan    schedule 16.11.2012