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 / 698502
Accepted
Sollosa
Sollosa
Asked: 2022-04-09 08:42:21 +0800 CST2022-04-09 08:42:21 +0800 CST 2022-04-09 08:42:21 +0800 CST

ecoando valor nos mesmos índices de 2 arrays simultaneamente

  • 772

Eu tenho 2 arrays para prcoess no script bash simultaneamente. O primeiro array contém tipos de rótulos. A segunda matriz contém valores, como em

LABELS=(label1 label2 label3 labe4 )
VALUES=(91 18 7 4)

O que é necessário é: um loop que ecoará o item indexado da matriz LABELS & e na frente desse valor correspondente para esse item da matriz VALUES, como em

label1 91
label2 18
label3 7
label4 4

Acho que o loop aninhado não funcionará, tentei abaixo, mas não funcionará pela sintaxe

for label in {LABELS[@]} && value in {VALUES[@]}
do
    echo ${label} ${value}
done
bash shell-script
  • 5 5 respostas
  • 904 Views

5 respostas

  • Voted
  1. terdon
    2022-04-09T08:49:40+08:002022-04-09T08:49:40+08:00

    Basta usar um índice numérico e referenciar os elementos da matriz por seu índice:

    labels=(label1 label2 label3 label4)
    values=(91 18 7 4)
    
    
    for((i=0; i<"${#labels[@]}"; i++ )); do
      printf '%s: %s\n' "${labels[i]}" "${values[i]}"
    done
    

    Ou, se você estiver usando um bash relativamente recente (>= versão 4) ou outro shell que suporte arrays associativos, basta usar um único array:

    declare -A values=( ["label1"]=91 ["label2"]=18 \
                        ["label3"]=7 ["label4"]=4 )
    
    for label in "${!values[@]}"; do
      printf '%s: %s\n' "$label" "${values[$label]}"
    done
    

    Mudei seus nomes de variáveis ​​para letras minúsculas porque é uma prática ruim usar CAPS para variáveis ​​locais em scripts de shell, pois as variáveis ​​de ambiente globais são capitalizadas por convenção, portanto, usar caps em seus scripts pode levar a colisões de nomes de variáveis.

    • 4
  2. cas
    2022-04-09T18:10:27+08:002022-04-09T18:10:27+08:00

    Como ambos os seus arrays têm exatamente os mesmos índices (0, 1, 2 e 3), você pode usar ${!array[@]}para iterar sobre os índices (chaves AKA) de um dos arrays e usar esse iterador para acessar os valores em ambos os arrays.

    Isso funciona com "matrizes indexadas" (ou seja, com índices inteiros) e "matrizes associativas" (índices de string).

    por exemplo

    LABELS=(label1 label2 label3 labe4 )
    VALUES=(91 18 7 4)
    
    for i in "${!LABELS[@]}"; do
      echo "${LABELS[i]}" "${VALUES[i]}"
    done
    

    Resultado:

    label1 91
    label2 18
    label3 7
    labe4 4
    

    BTW, você também pode usar um loop como este para preencher um array associativo, o que pode ser útil em situações em que você não pode apenas ler a chave e o valor ao mesmo tempo, como com seus dois arrays definidos manualmente:

    LABELS=(label1 label2 label3 labe4)
    VALUES=(91 18 7 4)
    
    declare -A LV # declare LV to be an associative array
    
    for i in "${!LABELS[@]}"; do
      LV["${LABELS[$i]}"]="${VALUES[$i]}";
    done
    
    declare -p LV
    

    Resultado:

    declare -A LV=([labe4]="4" [label3]="7" [label2]="18" [label1]="91" )
    

    A partir de agora, seu script pode usar array associativo $LVpara acessar diretamente o valor da chave, por exemplo

    $ echo "${LV[label1]}"
    91
    

    Você também pode usar um loop for no estilo C como nas respostas de @terdon e @NickMatteo (loop de 0 ao comprimento do array), mas isso só funciona se os índices do array forem numéricos e consecutivos sem lacunas (índices indefinidos) no array .

    Em muitos/na maioria dos casos, isso é bom porque as matrizes geralmente são definidas com números de índice consecutivos, mas em outros casos não funcionará como esperado - por exemplo, se $arraytiver definido índices para 1, 3, 5, 7, 11, 13, 17 then ${#array[@]}retornará 7 e tal loop irá iterar de 0..6 (ou 0..7 se você usar <=em vez de <como condição de teste) em vez da lista de índices reais na matriz.

    Por exemplo:

    $ for i in 1 3 5 7 11 13 17 ; do let array[$i]=$i*$i ; done
    
    $ declare -p array
    declare -a array=([1]="1" [3]="9" [5]="25" [7]="49" [11]="121" [13]="169" [17]="289")
    
    $ echo "${#array[@]}"
    7
    
    $ for ((i=0; i<"${#array[@]}"; i++)); do echo $i: "${array[$i]}" ; done
    0: 
    1: 1
    2: 
    3: 9
    4: 
    5: 25
    6: 
    
    $ echo "${!array[@]}"
    1 3 5 7 11 13 17
    
    $ for i in "${!array[@]}"; do echo $i: "${array[$i]}"; done
    1: 1
    3: 9
    5: 25
    7: 49
    11: 121
    13: 169
    17: 289
    
    • 4
  3. Best Answer
    Nick Matteo
    2022-04-09T08:48:53+08:002022-04-09T08:48:53+08:00

    Basta fazer um loop sobre os índices. por exemplo

    for (( i = 0; i < "${#LABELS[@]}"; i++ ))
    do echo "${LABELS[$i]} ${VALUES[$i]}"
    done
    

    Em vez de echo, você pode usar printfpara mais controle de formato, por exemplo

    printf '%6s: %3d\n' "${LABELS[$i]}" "${VALUES[$i]}"
    

    para alinhar etiquetas com até 6 letras e números com até 3 dígitos.

    • 3
  4. Stéphane Chazelas
    2022-04-09T10:48:21+08:002022-04-09T10:48:21+08:00

    Para aqueles que não precisam usar bash, zshusando seu ${arrayA:^arrayB} operador de compactação de matriz:

    $ labels=(label1 label2 label3 labe4 )
    $ values=(91 18 7 4)
    $ for k v (${labels:^values}) print -r -- "$k => $v"
    label1 => 91
    label2 => 18
    label3 => 7
    labe4 => 4
    

    Embora você nem precise do loop:

    $ print -raC2 -- ${labels:^values}
    label1  91
    label2  18
    label3  7
    labe4   4
    

    prints-los raw acruz em 2 Ccolunas.

    $ printf '%6s => %d\n' ${labels:^values}
    label1 => 91
    label2 => 18
    label3 => 7
     labe4 => 4
    

    No entanto, aqui você também pode fazer:

    $ print -rC2 -- $labels $values
    label1  91
    label2  18
    label3  7
    labe4   4
    

    Para printessas duas matrizes raw em 2 Ccolunas (deixando de fora -aaqui).

    Observe que você pode criar uma matriz associativa dessas duas matrizes (o que parece fazer mais sentido aqui) com:

    typeset -A assoc
    assoc=( ${labels:^values} )
    

    Se rótulos ou valores podem incluir a string vazia, você prefere usar:

    assoc=( "${(@)labels:^values}" )
    

    para preservá-los.

    E depois:

    print -raC2 -- ${(kv)assoc}
    

    Para print kolhos e valores raw, acruze em 2 Ccolunas ou para preservar chaves/valores vazios:

    print -raC2 -- "${(@kv)assoc}"
    

    Ou:

    for key value ("${(@kv)assoc}") print -r -- "$key => value"
    

    Ou:

    for key ("${(@k)assoc}") print -r -- "$key => $assoc[$key]"
    

    Cuidado, porém, que a ordem na qual os itens do array associativo são expandidos não é especificada.

    • 3
  5. Kusalananda
    2022-04-09T14:00:25+08:002022-04-09T14:00:25+08:00

    Copiando uma das matrizes para o conjunto de parâmetros posicionais e, em seguida, usando $1no loop para acessar o primeiro deles. Com shift, o primeiro parâmetro posicional é deslocado da lista e o que antes era o segundo elemento se torna o primeiro.

    LABELS=(label1 label2 label3 labe4 )
    VALUES=(91 18 7 4)
    
    set -- "${VALUES[@]}"
    
    for label in "${LABELS[@]}"; do
        printf '%s\t%s\n' "$label" "$1"
        shift
    done
    

    Isso evita o uso de indexação para obter os elementos da matriz dentro do loop.

    Saída (delimitada por tabulação):

    label1  91
    label2  18
    label3  7
    labe4   4
    
    • 3

relate perguntas

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

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

  • MySQL Select com função IN () com array bash

  • 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