Práce s poli v Linux Shell Scripting – část 8
Nedokážeme si představit programovací jazyk bez konceptu polí. Nezáleží na tom, jak jsou implementovány mezi různými jazyky. Místo toho nám pole pomáhají při konsolidaci dat, podobných nebo odlišných, pod jedním symbolickým názvem.
Protože se zabýváme skriptováním shellu, tento článek vám pomůže pohrát si s některými skripty shellu, které využívají tento koncept polí.
Inicializace a použití pole
S novějšími verzemi bash podporuje jednorozměrná pole. Pole může být explicitně deklarováno pomocí shell-builtin declare.
declare -a var
Ale není nutné deklarovat proměnné pole, jak je uvedeno výše. Jednotlivé prvky můžeme vkládat přímo do pole následovně.
var[XX]=<value>
kde „XX“ označuje index pole. K dereferenci prvků pole použijte syntaxi složených závorek, tj.
${var[XX]}
Poznámka: Indexování pole vždy začíná 0.
Dalším pohodlným způsobem inicializace celého pole je použití dvojice závorek, jak je uvedeno níže.
var=( element1 element2 element3 . . . elementN )
Existuje ještě další způsob přiřazování hodnot do polí. Tento způsob inicializace je podkategorií výše popsané metody.
array=( [XX]=<value> [XX]=<value> . . . )
Můžeme také číst/přiřazovat hodnoty do pole během doby provádění pomocí shell-builtin read.
read -a array
Nyní po provedení výše uvedeného příkazu uvnitř skriptu čeká na nějaký vstup. Potřebujeme poskytnout prvky pole oddělené mezerou (a ne návrat vozíku). Po zadání hodnot stiskněte enter pro ukončení.
K procházení prvky pole můžeme také použít for loop.
for i in “${array[@]}”
do
#access each element as $i. . .
done
Následující skript shrnuje obsah této konkrétní části.
#!/bin/bash
array1[0]=one
array1[1]=1
echo ${array1[0]}
echo ${array1[1]}
array2=( one two three )
echo ${array2[0]}
echo ${array2[2]}
array3=( [9]=nine [11]=11 )
echo ${array3[9]}
echo ${array3[11]}
read -a array4
for i in "${array4[@]}"
do
echo $i
done
exit 0
Různé operace na polích
Mnoho standardních operací s řetězci funguje na polích. Podívejte se na následující ukázkový skript, který implementuje některé operace s poli (včetně operací s řetězci).
#!/bin/bash
array=( apple bat cat dog elephant frog )
#print first element
echo ${array[0]}
echo ${array:0}
#display all elements
echo ${array[@]}
echo ${array[@]:0}
#display all elements except first one
echo ${array[@]:1}
#display elements in a range
echo ${array[@]:1:4}
#length of first element
echo ${#array[0]}
echo ${#array}
#number of elements
echo ${#array[*]}
echo ${#array[@]}
#replacing substring
echo ${array[@]//a/A}
exit 0
Následuje výstup vytvořený při provádění výše uvedeného skriptu.
apple
apple
apple bat cat dog elephant frog
apple bat cat dog elephant frog
bat cat dog elephant frog
bat cat dog elephant
5
5
6
6
Apple bAt cAt dog elephAnt frog
Myslím, že nemá žádný význam podrobně vysvětlovat výše uvedený skript, protože je samovysvětlující. V případě potřeby věnuji jeden díl této série výhradně manipulaci se strunami.
Náhrada příkazů pomocí polí
Náhrada příkazů přiřadí výstup příkazu nebo více příkazů do jiného kontextu. Zde v tomto kontextu polí můžeme vložit výstup příkazů jako jednotlivé prvky polí. Syntaxe je následující.
array=( $(command) )
Ve výchozím nastavení je obsah ve výstupu příkazu oddělený mezerami zasunut do pole jako jednotlivé prvky. Následující skript uvádí obsah adresáře, což jsou soubory s oprávněními 755.
#!/bin/bash
ERR=27
EXT=0
if [ $# -ne 1 ]; then
echo "Usage: $0 <path>"
exit $ERR
fi
if [ ! -d $1 ]; then
echo "Directory $1 doesn't exists"
exit $ERR
fi
temp=( $(find $1 -maxdepth 1 -type f) )
for i in "${temp[@]}"
do
perm=$(ls -l $i)
if [ `expr ${perm:0:10} : "-rwxr-xr-x"` -eq 10 ]; then
echo ${i##*/}
fi
done
exit $EXT
Simulace dvourozměrných polí
Můžeme snadno reprezentovat 2-rozměrnou matici pomocí 1-rozměrného pole. V řádkovém hlavním pořadí jsou prvky reprezentace v každém řádku matice postupně ukládány do indexů pole sekvenčním způsobem. Pro matici mXn lze vzorec pro totéž zapsat jako.
matrix[i][j]=array[n*i+j]
Podívejte se na další ukázkový skript pro přidání 2 matic a tisk výsledné matice.
#!/bin/bash
read -p "Enter the matrix order [mxn] : " t
m=${t:0:1}
n=${t:2:1}
echo "Enter the elements for first matrix"
for i in `seq 0 $(($m-1))`
do
for j in `seq 0 $(($n-1))`
do
read x[$(($n*$i+$j))]
done
done
echo "Enter the elements for second matrix"
for i in `seq 0 $(($m-1))`
do
for j in `seq 0 $(($n-1))`
do
read y[$(($n*$i+$j))]
z[$(($n*$i+$j))]=$((${x[$(($n*$i+$j))]}+${y[$(($n*$i+$j))]}))
done
done
echo "Matrix after addition is"
for i in `seq 0 $(($m-1))`
do
for j in `seq 0 $(($n-1))`
do
echo -ne "${z[$(($n*$i+$j))]}\t"
done
echo -e "\n"
done
exit 0
I když existují omezení pro implementaci polí uvnitř skriptování shellu, stává se užitečným v několika situacích, zvláště když řešíme substituci příkazů. Podíváme-li se z administrativního hlediska, koncept polí vydláždil cestu pro vývoj mnoha skriptů na pozadí v systémech GNU/Linux.