AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / unix / Perguntas / 748989
Accepted
Allan
Allan
Asked: 2023-06-16 02:46:46 +0800 CST2023-06-16 02:46:46 +0800 CST 2023-06-16 02:46:46 +0800 CST

Bash: convertendo uma string com espaços e aspas em uma matriz

  • 772

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 ”Foocom 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})
bash
  • 3 3 respostas
  • 72 Views

3 respostas

  • Voted
  1. Stéphane Chazelas
    2023-06-16T03:07:17+08:002023-06-16T03:07:17+08:00

    Em bash, você usaria readarraypara 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 fsinalizador de expansão de parâmetro (que divide na linha feed) e excluir o "(U+0022), “(U+0201C) e ”(U+ 201D), use o ${var//pattern[/replacement]}operador por exemplo:

    #! /bin/zsh -
    array=( ${(f)${"$(cmd)"//['"“”']}} ) || exit
    

    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 zshidioma, você também pode usar seu sinalizador z/ Z(para tokenizar o texto da mesma forma que o analisador de idioma faz) e Qsinalizador (para remover aspas) em vez de dividir por linha (o que assumiria que as strings entre aspas não podem abranger várias linhas).

    #! /bin/zsh -
    array=( ${(Q)${(Z[n])"$(cmd)"}} ) || exit
    

    Seu

    declare -a array=(${tempvar})
    

    in bashusa 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 $IFSparâ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:

    IFS=$'\n' # split on newline only:
    set -o noglob # disable the glob part which we don't want
    array=( $(cmd) ) # split+glob
    

    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]}

    array=( "${array[@]//['"“”']}" )
    

    Observe que, ao contrário da zshabordagem, isso não lidará com coisas como arquivos "foo \"bar\" and \\backslash".

    • 4
  2. Best Answer
    Nickotine
    2023-06-23T09:53:22+08:002023-06-23T09:53:22+08:00

    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:

    IFS=$'\n'
    
    arr=($(command <args>))
    

    Se você quiser 4 elementos sem aspas, faça isso:

    IFS=$'\n'
    
    arr=($(command <args> | sed s'#"##'g))
    

    Exemplo completo:

    IFS=$'\n'
    
    # tst.txt has your strings:
    arr=($(cat tst.txt | sed s'#"##'g))
    
    declare -p arr
    

    Saída:

    declare -a arr=([0]="Foo" [1]="FooBar" [2]="Foo Bar" [3]="FooBar/Foo Bar")
    
    • 1
  3. Hauke Laging
    2023-06-16T03:19:19+08:002023-06-16T03:19:19+08:00
    readarray -t array <<< $(echo $'"a a"\n"b   b"\n"c   c"')
    declare -p array
    declare -a array=([0]="\"a a\"" [1]="\"b   b\"" [2]="\"c   c\"")
    
    readarray -t array <<< $(command <args>)
    
    • -1

relate perguntas

  • exportar variáveis ​​​​env programaticamente, via stdout do comando [duplicado]

  • Problema estranho ao passar variáveis ​​do arquivo de texto

  • Enquanto a linha lê mantendo os espaços de escape?

  • ordem de substituição de processos `te` e `bash`

  • Execute um script muito lento até que seja bem-sucedido

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Possível firmware ausente /lib/firmware/i915/* para o módulo i915

    • 3 respostas
  • Marko Smith

    Falha ao buscar o repositório de backports jessie

    • 4 respostas
  • Marko Smith

    Como exportar uma chave privada GPG e uma chave pública para um arquivo

    • 4 respostas
  • Marko Smith

    Como podemos executar um comando armazenado em uma variável?

    • 5 respostas
  • Marko Smith

    Como configurar o systemd-resolved e o systemd-networkd para usar o servidor DNS local para resolver domínios locais e o servidor DNS remoto para domínios remotos?

    • 3 respostas
  • Marko Smith

    apt-get update error no Kali Linux após a atualização do dist [duplicado]

    • 2 respostas
  • Marko Smith

    Como ver as últimas linhas x do log de serviço systemctl

    • 5 respostas
  • Marko Smith

    Nano - pule para o final do arquivo

    • 8 respostas
  • Marko Smith

    erro grub: você precisa carregar o kernel primeiro

    • 4 respostas
  • Marko Smith

    Como baixar o pacote não instalá-lo com o comando apt-get?

    • 7 respostas
  • Martin Hope
    user12345 Falha ao buscar o repositório de backports jessie 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl Por que a maioria dos exemplos do systemd contém WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky Como exportar uma chave privada GPG e uma chave pública para um arquivo 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll status systemctl mostra: "Estado: degradado" 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim Como podemos executar um comando armazenado em uma variável? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S Por que /dev/null é um arquivo? Por que sua função não é implementada como um programa simples? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 Como ver as últimas linhas x do log de serviço systemctl 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - pule para o final do arquivo 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla Por que verdadeiro e falso são tão grandes? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis Substitua a string em um arquivo de texto enorme (70 GB), uma linha 2017-12-30 06:58:33 +0800 CST

Hot tag

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve