como mudar o valor da matriz no bash

8

queremos construir 6 pastas de pontos de montagem como exemplo

/data/sdb
/data/sdc
/data/sdd
/data/sde
/data/sdf
/data/sdg

então escrevemos esse script bash simples usando array

folder_mount_point_list="sdb sdc sdd sde sdf sdg"

folderArray=( $folder_mount_point_list )

counter=0
for i in disk1 disk2 disk3 disk4 disk4 disk5 disk6
do
folder_name=${folderArray[counter]}
mkdir /data/$folder_name
let counter=$counter+1
done

agora queremos mudar o código sem contador e vamos = $ counter = counter + 1

é possível mudar cada loop da matriz para obter o próximo valor da matriz?

como algo como

${folderArray[++]}
yael
fonte
1
o que é for i in disk1 disk2 disk3 disk4 disk4 disk5 disk6para como ele não está sendo usado dentro do corpo de loop?
RomanPerekhrest
1
... e qual é o sentido de usar um contador? Por que você simplesmente não corre for i in "your_list_goes_here"; do mkdir /data/"$i"; done?
don_crissti

Respostas:

10

Uma observação geral. Não faz sentido definir uma matriz como esta:

folder_mount_point_list="sdb sdc sdd sde sdf sdg"
folderArray=( $folder_mount_point_list )

Você faria isso:

folderArray=(sdb sdc sdd sde sdf sdg)

Agora à sua pergunta:

set -- sdb sdc sdd sde sdf sdg
for folder_name; do
    mkdir "/data/$folder_name"
done

ou

set -- sdb sdc sdd sde sdf sdg
while [ $# -gt 0 ]; do
    mkdir "/data/$1"
    shift
done
Hauke ​​Laging
fonte
podemos fazer o conjunto para a variável como set - $ list_of_folders (while list_of_folders = "sdb sdc sdc sdd sde")
yael
@yael Sim, você pode usar set -- $list_of_foldersmais uma vez: Variáveis ​​de seqüência de caracteres não são o caminho a seguir:set -- "${folders[@]}"
Hauke ​​Laging
1
por que você está usando set -- ....? esse hack é necessário apenas em shells que não suportam matrizes - não é necessário em um shell que suporta matrizes. for folder_name in "${folderArray[@]}"; do ... ; doneé tudo o que é necessário.
cas
Apenas uma pergunta, existe alguma opção para fazer algo como - $ {folderArray [++]}
yael 31/12/17
@cas é o que tenho na minha resposta. Também não entendo essa setabordagem.
PesaThe
14

Para responder à pergunta no título, você pode "mudar" uma matriz com a notação de substring / subarray. ( shiftele funciona apenas com os parâmetros posicionais.)

$ a=(a b c d e)
$ a=("${a[@]:1}")
$ echo "${a[@]}"
b c d e

Da mesma forma, para 'destacar' o último item da matriz: a=("${a[@]:0:${#a[@]} - 1}" )ouunset "a[${#a[@]}-1]"

Então, se você quiser, você pode fazer o seguinte:

a=(foo bar doo)
b=(123 456 789)
while [ "${#a[@]}" -gt 0 ] ; do
    echo "$a $b"
    a=("${a[@]:1}")
    b=("${b[@]:1}")
done

Mas isso destrói as matrizes, portanto, apenas a indexação como de costume pode ser melhor. Ou talvez use uma matriz associativa:

declare -A arr=([foo]=123 [bar]=456 [doo]=789)
ilkkachu
fonte
4

Você pode simplesmente fazer um loop sobre todos os valores, sem necessidade de mudança:

folderArray=(sdb sdc sdd sde sdf sdg)

for folder in "${folderArray[@]}"; do
    mkdir "/data/$folder"
done
PesaThe
fonte
3

Você não precisa de nenhum loop para isso:

folderArray=(sdb sdc sdd sde sdf sdg)
IFS=,
eval mkdir /data/{"${folderArray[*]}"}

O truque é que, se uma matriz é citada duas vezes com subscript *( "${array[*]}"), ela se expande para uma única palavra com o valor de cada elemento da matriz separado pelo primeiro caractere da IFSvariável. Depois disso, usamos o mecanismo de expansão de chaves para anexar /data/a cada membro da matriz e evalatualizar a coisa toda.

jimmij
fonte
Por que tão complicado? cd /data ; mkdir "${folderArray[@]}"Eu fiz o mesmo antes, mas não faria em um caso como este. Mas +1 para a abordagem avançada.
Hauke ​​Laging
@HaukeLaging Sim, isso seria mais simples em caso de mkdircomando. E até mesmo o array não é necessário, cd /data; mkdir abc defcomo faria uma pessoa normal. Mas não poderia ser tão simples para outras tarefas, por isso é bom saber como anexar rapidamente uma string a cada elemento da matriz sem um loop.
jimmij
Apenas uma pergunta, existe alguma opção para fazer algo como - $ {folderArray [++]}
yael 31/12/17
1
@yael Você pode fazer algo como echo "${folderArray[((counter++))]}"se realmente gosta dessa abordagem. O material interno (())é avaliado como matemática (observe falta de $na frente counter).
jimmij
1
e quando você começa a escrever um código de shell assim, percebe que dedicar um pouco de tempo a aprender perl ou python seria uma boa idéia. ou seja, apenas porque você pode fazer algo com o bash, não significa que você deveria .
cas