Eu tenho uma função (não criada por mim) que gera uma série de strings entre aspas:
command <args>
“Foo”
“FooBar”
“Foo Bar”
“FooBar/Foo Bar”
Quando tento atribuí-lo a um array (Bash; BSD/Mac), em vez de 4 elementos, obtenho 7. Por exemplo, para ${array[2]}
eu deveria obter “Foo Bar”
, mas em vez disso, obtenho ”Foo
com o próximo elemento sendo Bar”
. Qualquer elemento sem o espaço funciona corretamente (ou seja ${array[0]}
= “Foo”)
Como pode atribuir cada um desses elementos entre aspas incluindo o espaço para uma matriz que os elementos são separados por espaços (?) próprios?
No momento, estou pensando em usar sed/awk para “retirar” as aspas, mas acho que deve haver uma maneira melhor e mais eficiente.
Atualmente, estou atribuindo a saída do comando (parece exatamente com a saída acima, incluindo as aspas) a uma variável temporária e, em seguida, atribuindo-a a uma matriz.
_tempvar=“$(command <args>)”
declare -a _array=(${_tempvar})
Em
bash
, você usariareadarray
para ler as linhas de um arquivo ou da saída de algum comando em um array; no entanto, isso só foi adicionado na versão 4.0 lançada em 2009, mas o macos ainda vem com o bash 3.2.O macos vem com o zsh, que é um shell muito melhor.
Para obter as linhas não vazias da saída de um comando, você deve dividi-lo com o
f
sinalizador de expansão de parâmetro (que divide na linhaf
eed) e excluir o"
(U+0022),“
(U+0201C) e”
(U+ 201D), use o${var//pattern[/replacement]}
operador por exemplo:Se essas forem strings entre aspas com o caractere ASCII U+0022 e as aspas forem compatíveis com a forma como as aspas funcionam no
zsh
idioma, você também pode usar seu sinalizadorz
/Z
(para tokenizar o texto da mesma forma que o analisador de idioma faz) eQ
sinalizador (para remover aspas) em vez de dividir por linha (o que assumiria que as strings entre aspas não podem abranger várias linhas).Seu
in
bash
usa o operador split+glob que é invocado quando uma expansão é deixada (geralmente não intencionalmente) sem aspas. Ele divide a saída em caracteres do$IFS
parâmetro especial (que por padrão no bash contém espaço, tabulação e nova linha) usando um algoritmo complexo e as palavras resultantes sujeitas a globbing , também conhecido como geração de nome de arquivo (o que quase nunca é desejável).Aqui, split+glob pode ser usado para obter as linhas não vazias da saída do seu comando, mas você precisa ajustá-lo primeiro:
Em seguida, você também pode remover o
"“”
with , mas no bash isso deve ser feito posteriormente, pois não pode acumular operadores de expansão de parâmetros e a sintaxe (herdada de ksh93) é um pouco mais complicada:${var//pattern[/replacement]}
Observe que, ao contrário da
zsh
abordagem, isso não lidará com coisas como arquivos"foo \"bar\" and \\backslash"
.Você obtém 7 elementos porque a divisão de palavras está ocorrendo, causada pelos espaços.
Definido
IFS=$'\n'
antes de adicionar as strings ao array, você obterá 4 elementos, mas com aspas duplas.Exemplo:
Se você quiser 4 elementos sem aspas, faça isso:
Exemplo completo:
Saída: