Вы можете разделить по следующему шаблону:
\s*,\s*(?=((\\["\\]|[^"\\])*"(\\["\\]|[^"\\])*")*(\\["\\]|[^"\\])*$)
, который может выглядеть (немного) более дружелюбным с флагом (?x)
:
(?x) # enable comments, ignore space-literals
\s*,\s* # match a comma optionally surrounded by space-chars
(?= # start positive look ahead
( # start group 1
( # start group 2
\\["\\] # match an escaped quote or backslash
| # OR
[^"\\] # match any char other than a quote or backslash
)* # end group 2, and repeat it zero or more times
" # match a quote
( # start group 3
\\["\\] # match an escaped quote or backslash
| # OR
[^"\\] # match any char other than a quote or backslash
)* # end group 3, and repeat it zero or more times
" # match a quote
)* # end group 1, and repeat it zero or more times
( # open group 4
\\["\\] # match an escaped quote or backslash
| # OR
[^"\\] # match any char other than a quote or backslash
)* # end group 4, and repeat it zero or more times
$ # match the end-of-input
) # end positive look ahead
Но даже в этой закомментированной версии это все еще монстр. На простом английском языке это регулярное выражение можно объяснить следующим образом:
Совпадение с запятой, которая необязательно окружена пробелами, только при взгляде впереди этой запятой (вплоть до конца строки!), Есть нулевое или четное количество кавычек при игнорировании экранированного кавычки или экранированные обратные слэши.
Так что, увидев это, вы, возможно, согласитесь с ColinD (да!), Что в этом случае лучше использовать какой-то синтаксический анализатор CSV.
Обратите внимание, что приведенное выше регулярное выражение оставит квоты вокруг токенов, то есть строка a,b,"c,d\"",e
(как литерал: "a,b,\"c,d\\\"\",e"
) будет разбита следующим образом:
a
b
"c,d\""
e