Разделить строку с помощью пользовательского разделителя, уважать и сохранять кавычки (одинарные или двойные) - PullRequest
0 голосов
/ 27 июня 2019

У меня есть строка, которая выглядит следующим образом:

>>> s = '1,",2, ",,4,,,\',7, \',8,,10,'
>>> s
'1,",2, ",,4,,,\',7, \',8,,10,'

Я хотел бы разбить ее, используя разные разделители ( не только пробелы ), и я также хочу уважать и сохранятькавычки (одинарные или двойные).

Ожидаемые результаты при разбиении s на разделитель ,:

['1', ',2, ', '', '4', '', '', ',7, ', '8', '', '10', '']

Ответы [ 2 ]

2 голосов
/ 28 июня 2019

Похоже, вы заново изобретаете модуль Python CSV. Батареи включены.

In [1]: import csv
In [2]: s = '1,",2, ",,4,,,\',7, \',8,,10,'
In [3]: next(csv.reader([s]))
Out[3]: ['1', ',2, ', '', '4', '', '', "'", '7', " '", '8', '', '10', '']

Я думаю, регулярные выражения часто не являются хорошим решением. Это может быть удивительно медленно в неожиданные моменты. В модуле csv можно настроить диалект и легко обработать любое количество строк / файлов.

Мне не удалось настроить csv для двух вариантов quotechar одновременно, но вам это действительно нужно?

In [4]: next(csv.reader([s], quotechar="'"))
Out[4]: ['1', '"', '2', ' "', '', '4', '', '', ',7, ', '8', '', '10', '']

или

In [5]: s = '1,",2, ",,4,,,",7, ",8,,10,'
In [6]: next(csv.reader([s]))
Out[6]: ['1', ',2, ', '', '4', '', '', ',7, ', '8', '', '10', '']
0 голосов
/ 27 июня 2019

Модифицированная версия этого (которая обрабатывает только пробелы) может сделать трюк ( кавычки удалены ):

>>> import re
>>> s = '1,",2, ",,4,,,\',7, \',8,,10,'

>>> tokens = [t for t in re.split(r",?\"(.*?)\",?|,?'(.*?)',?|,", s) if t is not None ]
>>> tokens
['1', ',2, ', '', '4', '', '', ',7, ', '8', '', '10', '']

А если вам нравится оставьте кавычки символов:

>>> tokens = [t for t in re.split(r",?(\".*?\"),?|,?('.*?'),?|,", s) if t is not None ]
>>> tokens
['1', '",2, "', '', '4', '', '', "',7, '", '8', '', '10', '']

Если вы хотите использовать пользовательский разделитель , заменяйте каждое вхождение , в регулярном выражении своим собственным разделителем.

Объяснение

| = match alternatives e.g. ( |X) = space or X
.* = anything
x? = x or nothing
() = capture the content of a matched pattern

We have 3 alternatives:

1 "text"    -> ".*?" -> due to escaping rules becomes - > \".*?\"
2 'text'    -> '.*?'
3 delimiter ->  ,

Since we want to capture the content of the text inside the quotes, we use ():

1 \"(.*?)\"   (to keep the quotes use (\".*?\")
2 '(.*?)'     (to keep the quotes use ('.*?')

Finally we don't want that split function reports an empty match if a
delimiter precedes and follows quotes, so we capture that possible
delimiter too:

1 ,?\"(.*?)\",?
2 ,?'(.*?)',?

Once we use the | operator to join the 3 possibilities we get this regexp:

r",?\"(.*?)\",?|,?'(.*?)',?|,"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...