Как я могу разобрать запятую строку в списке (предостережение)? - PullRequest
24 голосов
/ 23 сентября 2008

Мне нужно иметь возможность взять строку вроде:

'''foo, bar, "one, two", three four'''

в

['foo', 'bar', 'one, two', 'three four']

У меня есть ощущение (с подсказками из #python), что решение будет включать модуль shlex.

Ответы [ 6 ]

40 голосов
/ 23 сентября 2008

Зависит от того, насколько сложным вы хотите стать ... хотите ли вы использовать более одного типа цитирования. Как насчет кавычек?

Ваш синтаксис очень похож на обычный формат файла CSV, который поддерживается стандартной библиотекой Python:

import csv
reader = csv.reader(['''foo, bar, "one, two", three four'''], skipinitialspace=True)
for r in reader:
  print r

Выходы:

['foo', 'bar', 'one, two', 'three four']

НТН!

26 голосов
/ 23 сентября 2008

Модульное решение shlex позволяет экранировать кавычки, одну кавычку экранировать другую, а также поддерживает все модные вещи.

>>> import shlex
>>> my_splitter = shlex.shlex('''foo, bar, "one, two", three four''', posix=True)
>>> my_splitter.whitespace += ','
>>> my_splitter.whitespace_split = True
>>> print list(my_splitter)
['foo', 'bar', 'one, two', 'three', 'four']

пример экранированных кавычек:

>>> my_splitter = shlex.shlex('''"test, a",'foo,bar",baz',bar \xc3\xa4 baz''',
                              posix=True) 
>>> my_splitter.whitespace = ',' ; my_splitter.whitespace_split = True 
>>> print list(my_splitter)
['test, a', 'foo,bar",baz', 'bar \xc3\xa4 baz']
5 голосов
/ 23 сентября 2008

Вы также можете рассмотреть модуль csv . Я не пробовал, но похоже, что ваши входные данные ближе к CSV, чем к синтаксису оболочки (именно это анализирует shlex).

1 голос
/ 23 сентября 2008

Вы можете сделать что-то вроде этого:

>>> import re
>>> pattern = re.compile(r'\s*("[^"]*"|.*?)\s*,')
>>> def split(line):
...  return [x[1:-1] if x[:1] == x[-1:] == '"' else x
...          for x in pattern.findall(line.rstrip(',') + ',')]
... 
>>> split("foo, bar, baz")
['foo', 'bar', 'baz']
>>> split('foo, bar, baz, "blub blah"')
['foo', 'bar', 'baz', 'blub blah']
0 голосов
/ 01 октября 2008

Я бы сказал, что регулярное выражение - это то, что вы ищете здесь, хотя я не очень знаком с движком Python Regex.

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

0 голосов
/ 23 сентября 2008

Если это не должно быть красиво, это может помочь вам:

def f(s, splitifeven):
    if splitifeven & 1:
        return [s]
    return [x.strip() for x in s.split(",") if x.strip() != '']

ss = 'foo, bar, "one, two", three four'

print sum([f(s, sie) for sie, s in enumerate(ss.split('"'))], [])
...