Поиск по сайту:

Работа с массивами в сценариях оболочки Linux – часть 8


Мы не можем представить язык программирования без понятия массивов. Неважно, как они реализованы в разных языках. Вместо этого массивы помогают нам объединить данные, похожие или разные, под одним символическим именем.

Поскольку нас интересуют сценарии оболочки, эта статья поможет вам поэкспериментировать с некоторыми сценариями оболочки, использующими концепцию массивов.

Инициализация и использование массива

В более новых версиях bash поддерживаются одномерные массивы. Массив может быть явно объявлен с помощью встроенной оболочки declare.


declare -a var  

Но нет необходимости объявлять переменные массива, как указано выше. Мы можем вставлять отдельные элементы в массив напрямую следующим образом.


var[XX]=<value>

где «XX» обозначает индекс массива. Для разыменования элементов массива используйте синтаксис фигурных скобок, т.е.


${var[XX]}

Примечание. Индексация массива всегда начинается с 0.

Другой удобный способ инициализации всего массива — использование пары круглых скобок, как показано ниже.


var=( element1 element2 element3 . . . elementN )

Существует еще один способ присвоения значений массивам. Этот способ инициализации является подкатегорией ранее объясненного метода.


array=( [XX]=<value> [XX]=<value> . . . )

Мы также можем читать/присваивать значения массиву во время выполнения, используя встроенную функцию оболочки read.


read -a array

Теперь после выполнения приведенного выше оператора внутри сценария он ожидает ввода. Нам нужно предоставить элементы массива, разделенные пробелом (а не возвратом каретки). После ввода значений нажмите Enter для завершения.

Для перемещения по элементам массива мы также можем использовать цикл for.


for i in “${array[@]}”
do
	#access each element as $i. . .
done 

Следующий скрипт суммирует содержимое этого конкретного раздела.


#!/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

Различные операции с массивами

Многие стандартные строковые операции работают с массивами. Посмотрите на следующий пример сценария, который реализует некоторые операции с массивами (включая операции со строками).


#!/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

Ниже приводится результат выполнения приведенного выше сценария.


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

Я думаю, что нет смысла подробно объяснять приведенный выше сценарий, поскольку он говорит сам за себя. При необходимости одну часть этой серии я посвящу исключительно манипуляциям со строками.

Замена команд с помощью массивов

Подстановка команд присваивает вывод команды или нескольких команд другому контексту. Здесь, в контексте массивов, мы можем вставить вывод команд как отдельные элементы массивов. Синтаксис следующий.


array=( $(command) )

По умолчанию содержимое вывода команды, разделенное пробелами, подключается к массиву как отдельные элементы. Следующий скрипт перечисляет содержимое каталога, то есть файлы с разрешениями 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

Моделирование двумерных массивов

Мы можем легко представить двумерную матрицу, используя одномерный массив. В основном порядке строк элементы представления в каждой строке матрицы последовательно сохраняются в индексах массива. Для матрицы mXn формула может быть записана как.


matrix[i][j]=array[n*i+j]

Посмотрите еще один пример сценария для добавления двух матриц и печати полученной матрицы.


#!/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 

Несмотря на то, что существуют ограничения на реализацию массивов внутри сценариев оболочки, в ряде ситуаций это становится полезным, особенно когда мы имеем дело с подстановкой команд. С административной точки зрения концепция массивов проложила путь для разработки многих фоновых сценариев в системах GNU/Linux.