Это на самом деле трудная вещь.
Это может быть сделано с заглядыванием / утверждениями за спиной.
Хотя не очень интуитивно понятно.
Это выглядит примерно так:
(?:^|,)(\s*"(?=(?:[^"]+|"")*"\s*(?:,|$)))?((?<=")(?:[^"]+|"")*(?="\s*(?:,|$))|[^,]*)
Как это работает - выстроить текстовое тело после первой кавычки "
в допустимом поле в кавычках.Если это поле не является допустимым в кавычках, оно выравнивается по самой кавычке.В этот момент текстовое тело может быть захвачено либо как поле без кавычек, либо как поле с кавычками минус кавычки, в одном буфере захвата.
Это, вероятно, регулярное выражение, которое дает точное решение безнеобходимость остаточного кода.Я мог что-то упустить, но я не вижу способа сделать это без обходных утверждений.Таким образом, ваш двигатель должен поддерживать это.Если нет, вам придется выбрать его, как показано выше.
Вот прототип на Perl с прокомментированным расширенным регулярным выражением под ним.
Удачи!
$samp = ' "hello " , world",,me,and,th""is, or , "tha""t" ';
$regex = '
(?: ^ | , )
(\s*" (?= (?:[^"]+|"")* " \s*(?:,|$) ) )?
(
(?<=") (?:[^"]+|"")* (?="\s*(?:,|$) )
|
[^,]*
)
';
while ($samp =~ /$regex/xg)
{
print "'$2'\n";
}
Вывод
'hello '
' world"'
''
'me'
'and'
'th""is'
' or '
'tha""t'
Комментируется
(?: ^ | , ) # Consume comma (or BOL is fine)
( # Capture group 1, capture '"' only if a complete quoted field
\s* # Optional many spaces
"
(?= # Lookahead, check for a valid quoted field, determines if a '"' will be consumed
(?:[^"]+|"")*
"
\s*
(?:,|$)
)
)? # End capt grp 1. 0 or 1 quote
( # Capture group 2, the body of text
(?<=") # If there is a '"' behind us, we have consumed a '"' in capture grp 1, so this is valid
(?:[^"]+|"")*
(?="\s*(?:,|$) )
| # OR,
[^,]* # Just get up to the next ',' This could be incomplete quoted fields
) # End capt grp 2
Расширение
Если на самом деле вы можете использовать это, его можно ускорить для потребленияцитируемое поле с обратными ссылками
вместо того, чтобы совпадать с цитируемым полем дважды.Обратные ссылки обычно преобразуются в одну строку
API сравнения, например strncmp()
на языке Си, что делает его намного быстрее.
В качестве дополнительного примечания, пробелы перед / после тела поля не заключенных в кавычки полей можно обрезать
внутри регулярного выражения с небольшим дополнительным обозначением.
Удачи!
Сжатый
(?:^|,)(?:\s*"(?=((?:[^"]+|"")*)"\s*(?:,|$)))?((?<=")\1|[^,]*)
Расширенный
(?: ^|, )
(?: \s* " (?= ( (?:[^"]+|"")* ) " \s* (?: ,|$ ) ))?
( (?<=") \1 | [^,]* )
Расширенный с комментариями
(?: ^ | , ) # Consume comma (or BOL is fine)
(?: # Start grouping
\s* # Spaces, then double quote '"' (consumed if valid quoted field)
" #
(?= # Lookahead, nothing consumed (check for valid quoted field)
( # Capture grp 1
(?:[^"]+|"")* # Body of quoted field (stored for later consumption)
) # End capt grp 1
" # Double quote '"'
\s* # Optional spaces
(?: , | $ ) # Comma or EOL
) # End lookahead
)? # End grouping, optionaly matches and consumes '\s*"'
( # Capture group 2, consume FIELD BODY
(?<=") # Lookbehind, if there is a '"' behind us the field is quoted
\1 # Consume capt grp 1
| # OR,
[^,]* # Invalid-quoted or Non-quoted field, get up to the next ','
) # End capt grp 2