Усложнённое разделение строки
Есть строка примерно такого вида -
str = 'a, b, c, d, "e, f, g"'
Суть в том, что нужно split эту строку по запятой, но не сплитить элементы внутри двойных кавычек.
Пример того, что нужно получить:
['a', 'b', 'c', 'd', "e, f, g"]
вот код, что есть, но он не сохраняет порядка, потому использование нецелесообразно 
Ответы (5 шт):
Можно попробовать обработать строку через tokenize.
Пример:
import io
import tokenize as T
from operator import itemgetter
def tokenize_string(data):
tokens = T.tokenize(io.BytesIO(data.strip().encode()).readline)
next(tokens) # skip encoding token
return list(filter(None, map(itemgetter(1), tokens))) # filter ENDMARKER
text = 'a, b, c, d, "e, f, g"'
tokens = [x for x in tokenize_string(text) if x != ',']
print(tokens)
# ['a', 'b', 'c', 'd', '"e, f, g"']
UPD.
Принудительное удаление кавычек из строки:
tokens = [x[1:-1] if x.startswith('"') and x.endswith('"') else x for x in tokenize_string(text) if x != ',']
print(tokens)
# ['a', 'b', 'c', 'd', 'e, f, g']
Могу предложить такой "топорный" метод
string = 'a, b, c, d, "e, f, g", 1, 2, 3, "5, 9, 0"'
index=0
max_index=len(string)
result=[]
while index < max_index:
if string[0]==' ':
string=string[1:]
elif string[index]==',':
result.append(string[:index])
string=string[index+1:]
max_index=len(string)
index=0
elif string[index]=='"':
result.append(string[index:string[index+1:].find('"')+3])
string=string[string[index+1:].find('"')+4:]
max_index=len(string)
index=0
else:
index+=1
print(result)
# ['a', 'b', 'c', 'd', '"e, f, g",', '1', '2', '3', '"5, 9, 0"']
Можно заменить составные элементы на одинарные (чтобы привести к общему случаю), затем провести необходимую манипуляцию - split, и потом вернуть на место из словаря составную часть
import re
t = 'a, b, c, d, "e, g, h", k'
# находим с помощью регулярных выражений составные элементы
x = re.findall('"[^\"]*"', t)
# объявляем словарик
d = dict()
# пробегаемся по списку наших составных элементов ['"e, g, h"']
# в n - у нас индекс элемента, в xx - сам элемент
for n, xx in enumerate(x):
# придумываем псевдоним для составного элемента на основе индекса
q = '@{}'.format(n)
# добавляем в словарь выходное значение составного элемента
d[q] = xx.replace('"', '')
# заменяем составной элемент на псевдоним
t = t.replace(xx, q)
# здесь 2 цикла, в первом текст t, который стал выглядеть вот так:
# 'a, b, c, d, @0, k' подвергаем split(','), а затем к каждому элементу
# применяем strip (s.strip())
# во втором цикле пробегаемся по всем элементам и если элемент (g) является
# ключом словаря (g in d) то заменяем его значением из словаря
tt = [d[g] if g in d else g for g in [s.strip() for s in t.split(',')]]
# ['a', 'b', 'c', 'd', 'e, g, h', 'k']
Моё решение. Работает с любым количеством вложенных в двойные кавычки элементов и любым количеством элементов с двойными кавычками.
def _recursive_filter(line, result=None):
try:
if not result:
result = []
line = line.strip()
if line.startswith('"'):
temp = ''
i = 0
while line[i+1] != '"':
temp += line[i]
i += 1
else:
temp += f'{line[i]}"'
result.append(temp)
line = line[len(temp):].strip(', ')
_recursive_filter(line, result)
else:
temp = ''
i = 0
while line[i] != ',':
temp += line[i]
i += 1
else:
temp += ','
result.append(temp)
line = line[len(temp):]
_recursive_filter(line, result)
return [x.strip(', "') for x in result]
except IndexError:
if temp:
result.append(temp)
if __name__ == "__main__":
print(_recursive_filter('"d, e, f", g, h,'))
def split_line(line, sep):
mas = line.split(str(sep))
kow = 0
new_mas = []
for i in mas:
if '"' in i and kow == 0:
kow = mas.index(i)
elif '"' in i and kow != 0:
new_mas.append(','.join(mas[kow:mas.index(i) + 1]).split('"')[1])
kow = 0
elif kow != 0:
pass
else:
new_mas.append(i)
return new_mas