Eu tenho uma string que é assim:
this is "a test"
Estou tentando escrever algo em Python para dividir por espaço, ignorando espaços entre aspas. O resultado que estou procurando é:
['this','is','a test']
PS. Eu sei que você vai perguntar "o que acontece se houver aspas dentro das aspas, bem, no meu pedido, isso nunca acontecerá.
Respostas:
Você deseja
split
, a partir doshlex
módulo embutido .Isso deve fazer exatamente o que você deseja.
fonte
shlex.split('this is "a test"', posix=False)
retorna['this', 'is', '"a test"']
shlex.split()
acionará umaUnicodeEncodeError
exceção.Dê uma olhada no
shlex
módulo, particularmenteshlex.split
.fonte
Vejo abordagens regex aqui que parecem complexas e / ou erradas. Isso me surpreende, porque a sintaxe do regex pode descrever facilmente "espaço em branco ou entre aspas", e a maioria dos mecanismos de regex (incluindo o Python) podem dividir-se em um regex. Portanto, se você usará expressões regulares, por que não dizer exatamente o que você quer dizer ?:
Explicação:
O shlex provavelmente fornece mais recursos, no entanto.
fonte
Dependendo do seu caso de uso, você também pode conferir o
csv
módulo:Resultado:
fonte
""
) para representar um aspas duplas"
, então vai virar duas aspas duplas em uma única citação'this is "a string""'
e'this is "a string"""'
será tanto mapa para['this', 'is', 'a string"']
Eu uso o shlex.split para processar 70.000.000 linhas de log do squid, é muito lento. Então eu mudei para re.
Por favor, tente isso, se você tiver problemas de desempenho com o shlex.
fonte
Como esta pergunta está marcada com regex, decidi tentar uma abordagem regex. Primeiro substituo todos os espaços nas partes das aspas por \ x00, depois divido por espaços, depois substituo o \ x00 pelos espaços em cada parte.
Ambas as versões fazem a mesma coisa, mas o splitter é um pouco mais legível que o splitter2.
fonte
Parece que, por razões de desempenho,
re
é mais rápido. Aqui está minha solução usando um operador menos ganancioso que preserva as aspas externas:Resultado:
Deixa construções como
aaa"bla blub"bbb
juntas, pois esses tokens não são separados por espaços. Se a sequência contiver caracteres de escape, você poderá corresponder assim:Observe que isso também corresponde à string vazia
""
por meio da\S
parte do padrão.fonte
,
via'(?:".*?"|[^,])+'
). O mesmo se aplica aos caracteres de citação (anexos).O principal problema com a
shlex
abordagem aceita é que ela não ignora caracteres de escape fora das substrings citadas e fornece resultados ligeiramente inesperados em alguns casos de canto.Eu tenho o seguinte caso de uso, em que preciso de uma função de divisão que divida as seqüências de entrada, de forma que as subseqüências entre aspas simples ou duplas sejam preservadas, com a capacidade de escapar aspas dentro dessa subseqüência. As aspas dentro de uma sequência não citada não devem ser tratadas de maneira diferente de qualquer outro caractere. Alguns exemplos de casos de teste com a saída esperada:
Eu terminei com a seguinte função para dividir uma string de modo que a saída esperada resulte em todas as strings de entrada:
O aplicativo de teste a seguir verifica os resultados de outras abordagens (
shlex
ecsv
por enquanto) e a implementação da divisão personalizada:Resultado:
Portanto, o desempenho é muito melhor
shlex
e pode ser aprimorado ainda mais pré-compilando a expressão regular, caso em que superará acsv
abordagem.fonte
shlex
que não se comporta conforme o esperado para meus casos de uso.Para preservar aspas, use esta função:
fonte
Teste de velocidade de respostas diferentes:
fonte
Hmm, parece que não consigo encontrar o botão "Responder" ... de qualquer maneira, esta resposta é baseada na abordagem de Kate, mas divide corretamente as seqüências de caracteres com substrings contendo aspas escapadas e também remove as aspas de início e fim das substrings:
Isso funciona em strings como
'This is " a \\\"test\\\"\\\'s substring"'
(a marcação insana é infelizmente necessária para impedir que o Python remova as fugas).Se as fugas resultantes nas seqüências de caracteres na lista retornada não forem desejadas, você poderá usar esta versão ligeiramente alterada da função:
fonte
Para contornar os problemas unicode em algumas versões do Python 2, sugiro:
fonte
split = lambda a: [b.decode('utf-8') for b in _split(a)]
caso contrário, você obtém:UnicodeDecodeError: 'ascii' codec can't decode byte ... in position ...: ordinal not in range(128)
Como opção, tente o tssplit:
fonte
Eu sugiro:
cadeia de teste:
para capturar também "" e '':
resultado:
ignorar vazio "" e '':
resultado:
fonte
re.findall("(?:\".*?\"|'.*?'|[^\s'\"]+)", s)
também.Se você não se importa com sub-strings, basta
Atuação:
Ou módulo de string
Desempenho: o módulo String parece ter um desempenho melhor que os métodos String
Ou você pode usar o mecanismo RE
atuação
Para cadeias muito longas, você não deve carregar a cadeia inteira na memória e, em vez disso, dividir as linhas ou usar um loop iterativo
fonte
Tente o seguinte:
Algumas seqüências de teste:
fonte
adamsplit("This is 'a test'")
→['This', 'is', "'a", "test'"]