Разбить строку на пробелы - сохраняя подстроки в кавычках - в Python - PullRequest
232 голосов
/ 17 сентября 2008

У меня есть строка, подобная этой:

this is "a test"

Я пытаюсь написать что-то в Python, чтобы разделить его на пробелы, игнорируя пробелы в кавычках. Результат, который я ищу:

['this','is','a test']

PS. Я знаю, что вы спросите «что произойдет, если в кавычках есть кавычки, ну, в моем приложении этого никогда не произойдет».

Ответы [ 16 ]

2 голосов
/ 25 июня 2012

Чтобы обойти проблемы с юникодом в некоторых версиях Python 2, я предлагаю:

from shlex import split as _split
split = lambda a: [b.decode('utf-8') for b in _split(a.encode('utf-8'))]
1 голос
/ 25 июля 2012

Проблемы с юникодом в shlex, рассмотренные выше (верхний ответ), по-видимому, решены (косвенно) в 2.7.2+ http://bugs.python.org/issue6988#msg146200

(отдельный ответ, потому что я не могу комментировать)

1 голос
/ 29 января 2010

Хм, не могу найти кнопку "Ответить" ... в любом случае, этот ответ основан на подходе Кейт, но правильно расщепляет строки с подстрокой, содержащей экранированные кавычки, а также удаляет начальные и конечные кавычки подстроки:

  [i.strip('"').strip("'") for i in re.split(r'(\s+|(?<!\\)".*?(?<!\\)"|(?<!\\)\'.*?(?<!\\)\')', string) if i.strip()]

Это работает с такими строками, как 'This is " a \\\"test\\\"\\\'s substring"' (к сожалению, безумная разметка необходима, чтобы Python не мог удалить escape-символы).

Если результирующие экранированные строки в возвращаемом списке не нужны, вы можете использовать эту слегка измененную версию функции:

[i.strip('"').strip("'").decode('string_escape') for i in re.split(r'(\s+|(?<!\\)".*?(?<!\\)"|(?<!\\)\'.*?(?<!\\)\')', string) if i.strip()]
0 голосов
/ 09 сентября 2015

Я предлагаю:

тестовая строка:

s = 'abc "ad" \'fg\' "kk\'rdt\'" zzz"34"zzz "" \'\''

для захвата также "" и '':

import re
re.findall(r'"[^"]*"|\'[^\']*\'|[^"\'\s]+',s)

результат:

['abc', '"ad"', "'fg'", '"kk\'rdt\'"', 'zzz', '"34"', 'zzz', '""', "''"]

игнорировать пустые "" и '':

import re
re.findall(r'"[^"]+"|\'[^\']+\'|[^"\'\s]+',s)

результат:

['abc', '"ad"', "'fg'", '"kk\'rdt\'"', 'zzz', '"34"', 'zzz']
0 голосов
/ 17 сентября 2008

Если вам не нужны подстроки, чем простая

>>> 'a short sized string with spaces '.split()

Производительность:

>>> s = " ('a short sized string with spaces '*100).split() "
>>> t = timeit.Timer(stmt=s)
>>> print "%.2f usec/pass" % (1000000 * t.timeit(number=100000)/100000)
171.39 usec/pass

Или строковый модуль

>>> from string import split as stringsplit; 
>>> stringsplit('a short sized string with spaces '*100)

Производительность: Строковый модуль работает лучше, чем строковые методы

>>> s = "stringsplit('a short sized string with spaces '*100)"
>>> t = timeit.Timer(s, "from string import split as stringsplit")
>>> print "%.2f usec/pass" % (1000000 * t.timeit(number=100000)/100000)
154.88 usec/pass

Или вы можете использовать двигатель RE

>>> from re import split as resplit
>>> regex = '\s+'
>>> medstring = 'a short sized string with spaces '*100
>>> resplit(regex, medstring)

Производительность

>>> s = "resplit(regex, medstring)"
>>> t = timeit.Timer(s, "from re import split as resplit; regex='\s+'; medstring='a short sized string with spaces '*100")
>>> print "%.2f usec/pass" % (1000000 * t.timeit(number=100000)/100000)
540.21 usec/pass

Для очень длинных строк не следует загружать всю строку в память и вместо этого либо разбивать строки, либо использовать итеративный цикл

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

Попробуйте это:

  def adamsplit(s):
    result = []
    inquotes = False
    for substring in s.split('"'):
      if not inquotes:
        result.extend(substring.split())
      else:
        result.append(substring)
      inquotes = not inquotes
    return result

Некоторые тестовые строки:

'This is "a test"' -> ['This', 'is', 'a test']
'"This is \'a test\'"' -> ["This is 'a test'"]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...