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 / 751144
Accepted
symcbean
symcbean
Asked: 2023-07-11 00:44:29 +0800 CST2023-07-11 00:44:29 +0800 CST 2023-07-11 00:44:29 +0800 CST

Bash gerenciar lista separada de espaço

  • 772

Eu tenho um script de shell bastante complexo que processa várias listas de valores que são lidos de um arquivo como valores separados por espaço, por exemplo

SET1="value1 value2 value3"

for i in ${SET1}; do
   ...

Agora quero criar uma lista formatada de forma semelhante no script para escrever. No entanto, se eu fizer (por exemplo) isso:

DISCOVERED=''
DISCOVERED+=( us-east-1 )
DISCOVERED+=( us-east-2 )
DISCOVERED+=( us-west-1 )
for REGION in ${DISCOVERED} ; do
    echo $REGION
done

Eu não recebo nenhuma saída. Eu recebo saída se eu especificar in ${DISCOVERED[@]}. Parece que estou trabalhando com diferentes tipos de dados em SET1 e DISCOVERED.

Posso anexar facilmente a uma string com valores separados por espaço, mas acabo com um espaço inicial ou final que precisa ser limpo:

function append_discovered {
   local VALUE="$1"
   if [ -z "${DISCOVERED}" ] ; then
      DISCOVERED="$VALUE"
   else
      DISCOVERED="${DISCOVERED} ${VALUE}"
   fi
}

.... mas isso parece bastante complicado.

Eu poderia tratar minha variável de saída como uma matriz - mas preciso convertê-la de volta ( DISCOVERED="${DISCOVERED[@]}") em locais apropriados para usar uma construção diferente para iterar por meio desta lista do que para as outras listas.

Qual é o tipo de dados para meus dados de entrada (por exemplo, $SET1 acima) se não for um array?

Existe uma maneira mais simples de anexar esta lista e manter o mesmo tipo de dados?

bash
  • 2 2 respostas
  • 66 Views

2 respostas

  • Voted
  1. Best Answer
    roaima
    2023-07-11T01:30:56+08:002023-07-11T01:30:56+08:00

    Parece que estou trabalhando com diferentes tipos de dados em SET1 e DISCOVERED

    De fato. SET1é uma corda. Acontece que você interpreta o valor da string como sendo vários elementos separados por espaço. DISCOVEREDpor outro lado é um array com vários elementos.

    set1='this is a string of seven words'
    discovered=('this' 'is' 'an' 'array' 'with' 'seven' 'elements')
    
    echo "$set1"
    echo "${discovered[@]}"
    

    Um problema com o seu SET1código no topo da sua pergunta é que cada elemento será globalizado e expandido. Portanto, se você tiver um arquivo chamado onebananatwoem seu diretório atual e encontrar um elemento one*, o globbing se expandirá one*para se tornar onebananatwo. (Evitar isso é o motivo pelo qual as variáveis ​​de aspas duplas são sempre altamente recomendadas.)

    Posso anexar facilmente a uma string com valores separados por espaços, mas acabo com um espaço inicial ou final que precisa ser limpo

    Você pode usar uma expansão condicional para inserir o espaço somente se a string não estiver vazia:

    append_discovered() {
        local value=$1
        discovered="$discovered${discovered:+ }$value"
    }
    

    (Observe que removi a palavra- functionchave não padrão e coloquei os nomes das variáveis ​​em letras minúsculas para que não entrem em conflito inesperado com as variáveis ​​reservadas.)

    Aqui está o que está acontecendo com $discovered${discovered:+ }$value:

    • Quando $discoveredé a string vazia, ${discovered:+ }também retorna uma string vazia e, portanto, o resultado é apenas$value
    • Quando $discoveredtem um valor, ${discovered:+ }retorna um espaço e, portanto, o resultado é uma string composta $discoverede $valueseparada por um único espaço

    No futuro, recomendo que você considere o uso de uma matriz para tipos de dados de matriz em vez de elementos separados por espaço em uma string, mas entendo que adaptar isso a um script existente pode não ser econômico ou sensato.

    • 3
  2. Sotto Voce
    2023-07-11T01:19:30+08:002023-07-11T01:19:30+08:00

    No bash 5.x do meu Mac, sua primeira sintaxe funciona:

    DISCOVERED=''
    DISCOVERED+=( us-east-1 )
    DISCOVERED+=( us-east-2 )
    DISCOVERED+=( us-west-1 )
    echo ${#DISCOVERED[@]}
    printf '"%s" ' "${DISCOVERED[@]}"
    echo
    

    A saída é:

    4
    "" "us-east-1" "us-east-2" "us-west-1"
    

    Talvez você esperasse que a DISCOVERED=''instrução excluísse todos os elementos da matriz em vez de definir o primeiro elemento como uma string vazia, então suas tentativas de expandir/retornar o primeiro elemento da matriz fizeram parecer que a matriz estava vazia?

    Se você quiser garantir que a variável da matriz seja limpa (sem elementos), sugiro DISCOVERED=()ou unset DISCOVERED.

    Editado para adicionar:

    Para gerar uma string delimitada a partir dos elementos da matriz, geralmente uso um simples de duas linhas. Este exemplo usa ' :' como caractere delimitador:

    printf -v SET1 '%s:' "${DISCOVERED[@]}"
    SET1="${SET1%:}"
    echo $SET1
    

    (Não incluí o primeiro elemento vazio da matriz) A saída:

    us-east-1:us-east-2:us-west-1
    

    Ele usa uma propriedade do built-in printfpara iterar os elementos da matriz, acrescentando o delimitador a cada um. (Viva, não preciso escrever um loop!) A segunda linha remove o delimitador final. Isso também funcionará com o caractere de espaço como delimitador, mas é mais fácil fazê-lo como SET1="${DISCOVERED[@]}". Não é muito elegante ter a segunda linha para retirar o último delimitador, mas funciona para muitos casos de uso, é simples, rápido e não chama comandos externos.

    • 2

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