У меня есть строка, которая выглядит так:
this is "a test"
Я пытаюсь написать что-то на Python, чтобы разделить его на пробелы, игнорируя пробелы в кавычках. Результат, который я ищу:
['this','is','a test']
PS. Я знаю, что вы спросите «что произойдет, если в кавычках есть кавычки, ну, в моем приложении, этого никогда не произойдет».
Ответы:
Вы хотите
split
, из встроенногоshlex
модуля.Это должно делать именно то, что вы хотите.
источник
shlex.split('this is "a test"', posix=False)
возвращается['this', 'is', '"a test"']
shlex.split()
юникоде вызоветUnicodeEncodeError
исключение.Посмотрите на
shlex
модуль, в частностиshlex.split
.источник
Я вижу подходы регулярных выражений здесь, которые выглядят сложными и / или неправильными. Это удивляет меня, потому что синтаксис регулярных выражений может легко описать «пробел или вещь, заключенную в кавычки», и большинство движков регулярных выражений (включая Python) могут разделяться на регулярные выражения. Так что, если вы собираетесь использовать регулярные выражения, почему бы просто не сказать точно, что вы имеете в виду ?:
Объяснение:
Shlex, вероятно, предоставляет больше возможностей, хотя.
источник
В зависимости от вашего варианта использования, вы также можете проверить
csv
модуль:Вывод:
источник
""
), чтобы представить одну двойную кавычку"
, поэтому превратят две двойные кавычки в одну кавычку'this is "a string""'
и'this is "a string"""'
оба сопоставят с['this', 'is', 'a string"']
Я использую shlex.split для обработки 7000000 строк журнала Squid, это очень медленно. Поэтому я перешел на ре.
Пожалуйста, попробуйте это, если у вас есть проблемы с производительностью shlex.
источник
Поскольку этот вопрос помечен регулярным выражением, я решил попробовать подход регулярного выражения. Сначала я заменяю все пробелы в частях кавычек на \ x00, затем делю на пробелы, а затем заменяю \ x00 на пробелы в каждой части.
Обе версии делают одно и то же, но разделитель немного читабельнее, чем разделитель2.
источник
Похоже, по соображениям производительности
re
это быстрее. Вот мое решение с использованием наименее жадного оператора, который сохраняет внешние кавычки:Результат:
Это оставляет конструкции как
aaa"bla blub"bbb
вместе, так как эти токены не разделены пробелами. Если строка содержит экранированные символы, вы можете сопоставить это так:Обратите внимание, что это также соответствует пустой строке
""
посредством\S
части шаблона.источник
,
через'(?:".*?"|[^,])+'
). То же самое относится к кавычкам (вмещающим) символам.Основная проблема с принятым
shlex
подходом состоит в том, что он не игнорирует escape-символы вне указанных в кавычках подстрок и дает несколько неожиданные результаты в некоторых угловых случаях.У меня есть следующий вариант использования, где мне нужна функция разбиения, которая разбивает входные строки так, чтобы подстроки с одинарными или двойными кавычками сохранялись, с возможностью экранирования кавычек внутри такой подстроки. Кавычки в строке без кавычек не должны трактоваться иначе, чем любой другой символ. Некоторые примеры тестовых случаев с ожидаемым выводом:
В итоге я получил следующую функцию, чтобы разбить строку таким образом, чтобы ожидаемые выходные результаты были получены для всех входных строк:
Следующее тестовое приложение проверяет результаты других подходов (
shlex
иcsv
пока) и пользовательскую реализацию разделения:Вывод:
Таким образом, производительность намного выше
shlex
и может быть улучшена путем предварительной компиляции регулярного выражения, и в этом случае он превзойдетcsv
подход.источник
shlex
поведение не соответствует ожидаемым для моих сценариев использования.Чтобы сохранить кавычки используйте эту функцию:
источник
Тест скорости разных ответов:
источник
Хм, похоже, не могу найти кнопку «Ответить» ... во всяком случае, этот ответ основан на подходе Кейт, но правильно разбивает строки на подстроки, содержащие экранированные кавычки, а также удаляет начальные и конечные кавычки подстрок:
Это работает с такими строками
'This is " a \\\"test\\\"\\\'s substring"'
(безумная разметка, к сожалению, необходима, чтобы Python не удалял экранированные символы).Если результирующие экранированные строки в возвращаемом списке не нужны, вы можете использовать эту слегка измененную версию функции:
источник
Чтобы обойти проблемы с юникодом в некоторых версиях Python 2, я предлагаю:
источник
split = lambda a: [b.decode('utf-8') for b in _split(a)]
противном случае вы получите:UnicodeDecodeError: 'ascii' codec can't decode byte ... in position ...: ordinal not in range(128)
Как вариант попробуйте tssplit:
источник
Я предлагаю:
тестовая строка:
захватить также «» и «»:
результат:
игнорировать пустые "" и "':
результат:
источник
re.findall("(?:\".*?\"|'.*?'|[^\s'\"]+)", s)
также.Если вам не нужны подстроки, чем простая
Производительность:
Или строковый модуль
Производительность: модуль String, кажется, работает лучше, чем строковые методы
Или вы можете использовать двигатель RE
Производительность
Для очень длинных строк не следует загружать всю строку в память и вместо этого либо разбивать строки, либо использовать итеративный цикл
источник
Попробуй это:
Некоторые тестовые строки:
источник
adamsplit("This is 'a test'")
→['This', 'is', "'a", "test'"]