разделить с указанием c запятой не в кавычках в python - PullRequest
3 голосов
/ 18 января 2020

у меня есть эта строка, и я хочу разделить ее на ","

x = 'a, b, c , d , "x,x,2" , hi'
x.split(',')

вот моя настоящая строка

x = 'Outward   ,Supply , ,Tax Invoice ,IN9195212470,31/12/2019,VPS AGRO & AUTO PVT LTD ,311954,06AAACV9344F1ZA ,"VILLAGE KHANPUR KOLIAN, N.H. 1 ",6 K.M. FRO,KURUKSHETRA   ,HARYANA ,136131,VPS AGRO & AUTO PVT LTD ,311954,"VILLAGE KHANPUR KOLIAN, N.H. 1",6 K.M. FRO,KURUKSHETRA                             ,HARYANA             ,136131,503675,SM VAL. GENUINE DIESEL ENG. OIL 1/9 L   ,27101980,360,LTR,58204.04,9,5238.36,9,5238.36,0,0,0,0,0,0,0,68680.76,                    ,                    ,                              ,          ,          ,,               ,          ,06AAACW0287A1ZR   ,VALVOLINE CUMMINS PVT LTD-AMBALA        ,"KHASHRA NO-108/1/2,                                         ",          ,AMBALA                                  ,133004,HARYANA             ,                    ,                  ,                              , ,'

она возвращает этот результат

['a','b','c','d','"x','x','2', 'hi']

Но я хочу иметь этот

['a', 'b', 'c' , 'd' , '"x,x,2"' , 'hi']

как это сделать в python

Помогите мне

Ответы [ 4 ]

3 голосов
/ 18 января 2020
import shlex
lexer = shlex.shlex('a, b, c , d , "x,x,2" , hi')
lexer.whitespace += ','
print(list(lexer))

Результат:

['a', 'b', 'c', 'd', '"x,x,2"', 'hi']

Вот обновленное решение для обновленной задачи:


x = 'Outward   ,Supply , ,Tax Invoice ,IN9195212470,31/12/2019,VPS AGRO & AUTO PVT LTD ,311954,06AAACV9344F1ZA ,"VILLAGE KHANPUR KOLIAN, N.H. 1 ",6 K.M. FRO,KURUKSHETRA   ,HARYANA ,136131,VPS AGRO & AUTO PVT LTD ,311954,"VILLAGE KHANPUR KOLIAN, N.H. 1",6 K.M. FRO,KURUKSHETRA                             ,HARYANA             ,136131,503675,SM VAL. GENUINE DIESEL ENG. OIL 1/9 L   ,27101980,360,LTR,58204.04,9,5238.36,9,5238.36,0,0,0,0,0,0,0,68680.76,                    ,                    ,                              ,          ,          ,,               ,          ,06AAACW0287A1ZR   ,VALVOLINE CUMMINS PVT LTD-AMBALA        ,"KHASHRA NO-108/1/2,                                         ",          ,AMBALA                                  ,133004,HARYANA             ,                    ,                  ,                              , ,'


import shlex
lexer = shlex.shlex(x)
lexer.whitespace = ','
lexer.whitespace_split = True
print([cell.strip() for cell in lexer])

Результат:

['Outward', 'Supply', '', 'Tax Invoice', 'IN9195212470', '31/12/2019', 'VPS AGRO & AUTO PVT LTD', '311954', '06AAACV9344F1ZA', '"VILLAGE KHANPUR KOLIAN, N.H. 1 "', '6 K.M. FRO', 'KURUKSHETRA', 'HARYANA', '136131', 'VPS AGRO & AUTO PVT LTD', '311954', '"VILLAGE KHANPUR KOLIAN, N.H. 1"', '6 K.M. FRO', 'KURUKSHETRA', 'HARYANA', '136131', '503675', 'SM VAL. GENUINE DIESEL ENG. OIL 1/9 L', '27101980', '360', 'LTR', '58204.04', '9', '5238.36', '9', '5238.36', '0', '0', '0', '0', '0', '0', '0', '68680.76', '', '', '', '', '', '', '', '06AAACW0287A1ZR', 'VALVOLINE CUMMINS PVT LTD-AMBALA', '"KHASHRA NO-108/1/2,                                         "', '', 'AMBALA', '133004', 'HARYANA', '', '', '', '']
1 голос
/ 18 января 2020

Вы можете использовать подход регулярного выражения:

import regex as re

x = 'a, b, c , d , "x,x,2" , hi'

rx = re.compile(
    r"""
    "[^"]*"(*SKIP)(*FAIL)
    |
    \s*,\s*
    """, re.VERBOSE)
lst = rx.split(x)
print(lst)

Это дает

['a', 'b', 'c', 'd', '"x,x,2"', 'hi']
1 голос
/ 18 января 2020

Решение, использующее только split. Обратите внимание, что он использует f строк (python 3.6+), но такое же поведение все еще может быть достигнуто в более старых версиях. Это можно сделать без использования регулярных выражений следующим образом: Я прокомментирую код для объяснения:

# First split by double quote
x = x.split('"')
final_x = []
for i in range(len(x)):
    # We know that if the list element is even then it must be outside double quotes
    if i%2 == 0:
        # Split the list by commas and strip any whitespace
        x_element = x[i].split(',')
        x_element = [el.strip() for el in x_element]
        # extend the list
        final_x.extend(x_element)
    else:
        # This is an odd element of the list, therefore inside quotation.
        # put the string back into quotations
        x_element = f'"{x[i]}"'
        #append this to the final list
        final_x.append(x_element)
# filter out any white spaces left from the various splits         
final_x = [el for el in final_x if el !=''] 

Обратите внимание на разницу в добавлении нечетных элементов списка и расширении четного. Это потому, что вы создаете новый список с разделением, и мы хотим расширить наш вывод, в то время как для нечетных элементов мы хотим добавить новый элемент в список, поэтому мы добавляем.

1 голос
/ 18 января 2020

Нет встроенных модулей, которые могли бы добиться этого без большого количества взлома для предварительной / последующей обработки данных.

  • shlex.split в некоторой степени сработает с этим примером, но это обман , поскольку он разбивается на пространства. Если 2 элемента сопоставлены только с запятыми, это не удастся.
  • ast.literal_eval не будет работать, поскольку ... некоторые элементы не являются литералами
  • csv.reader object почти делает то же самое с [x.strip() for x in next(csv.reader([x]))], но кавычки не обрабатываются должным образом, потому что между ними и запятыми есть пробелы.

Но, просматривая каждый символ с помощью простого конечного автомата, это можно сделать:

x = 'a, b, c , d , "x,x,2" , hi'

in_quote = False
current = []
output = []
for c in x:
    if in_quote:
        current.append(c)
        if c=='"':
            output.append("".join(current))
            current = []
            in_quote = False
        continue

    if c==",":
        output.append("".join(current))
        current = []
    elif c==" ":
        pass
    else:
        current.append(c)
        if c=='"':
            in_quote = True

output.append("".join(current))

результат:

['a', 'b', 'c', 'd', '"x,x,2"', '', 'hi']

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

В конец, не забудьте последний накопленный элемент при обнаружении конца строки.

...