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

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

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)

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

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.


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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.