Введение
В этом руководстве мы рассмотрим массивы Bash и научимся выводить каждый элемент на отдельной строке – это распространенный запрос в оболочном скриптинге. Массивы Bash позволяют хранить несколько значений в одной переменной, что делает их незаменимыми для организации данных в ваших скриптах.
К концу этого практического занятия (LabEx) вы поймете, как создавать массивы, манипулировать элементами массива и использовать различные методы для вывода содержимого массива по одному элементу на строку. Эти навыки помогут вам писать более эффективные и читаемые оболочечные скрипты для таких задач, как обработка списков файлов, обработка выходных данных команд и автоматизация задач системного администрирования.
Создание и понимание массивов Bash
Массивы Bash позволяют хранить несколько значений в одной переменной. Давайте научимся создавать их и работать с ними.
Создание первого массива
Откройте терминал в WebIDE. По умолчанию вы должны находиться в директории /home/labex/project. Начнем с создания простого скрипта Bash:
В WebIDE создайте новый файл с именем
array_demo.sh, нажав на иконку "New File" в панели проводника или выбрав опцию меню "File > New File".Добавьте в файл следующее содержимое:
#!/bin/bash
## Create an array of fruits
fruits=("apple" "banana" "orange" "grape" "kiwi")
## Print the entire array
echo "All fruits: ${fruits[@]}"
## Print the first element (index 0)
echo "First fruit: ${fruits[0]}"
## Print the third element (index 2)
echo "Third fruit: ${fruits[2]}"
## Print the number of elements in the array
echo "Number of fruits: ${#fruits[@]}"
Сохраните файл, нажав Ctrl+S или выбрав опцию меню "File > Save".
Теперь сделайте скрипт исполняемым, запустив следующую команду в терминале:
chmod +x /home/labex/project/array_demo.sh
- Запустите скрипт:
./array_demo.sh
Вы должны увидеть вывод, похожий на следующий:
All fruits: apple banana orange grape kiwi
First fruit: apple
Third fruit: orange
Number of fruits: 5
Понимание синтаксиса массивов
Разберем синтаксис массивов:
Создание массива:
fruits=("apple" "banana" "orange" "grape" "kiwi")Это создает массив с именемfruitsиз пяти элементов.Доступ к всем элементам:
${fruits[@]}Символ@обозначает все элементы массива.Доступ к определенному элементу:
${fruits[0]},${fruits[2]}Массивы в Bash имеют нулевой индекс, то есть первый элемент находится по индексу 0.Получение длины массива:
${#fruits[@]}Символ#перед ссылкой на массив возвращает количество элементов.
Различные способы создания массивов
Создадим новый скрипт, чтобы продемонстрировать различные способы создания массивов:
- Создайте новый файл с именем
array_creation.sh:
#!/bin/bash
## Method 1: Direct declaration
colors=("red" "green" "blue" "yellow")
echo "Colors array: ${colors[@]}"
## Method 2: Individual element assignment
shapes=()
shapes[0]="circle"
shapes[1]="square"
shapes[2]="triangle"
echo "Shapes array: ${shapes[@]}"
## Method 3: Create array from command output
files=($(ls /home/labex/project))
echo "Files in current directory: ${files[@]}"
## Method 4: Create array from a string
data="one two three four"
numbers=($data)
echo "Numbers array: ${numbers[@]}"
- Сохраните файл и сделайте его исполняемым:
chmod +x /home/labex/project/array_creation.sh
- Запустите скрипт:
./array_creation.sh
Вы должны увидеть вывод, показывающий все различные массивы, которые вы создали. Точный вывод для массива файлов будет зависеть от того, какие файлы существуют в вашей директории.
Эти примеры демонстрируют гибкость массивов Bash и то, как вы можете создавать их различными способами в зависимости от своих потребностей.
Манипуляция элементами массива
Теперь, когда мы знаем, как создавать массивы, давайте научимся манипулировать ими, добавляя, удаляя и изменяя элементы.
Изменение элементов массива
Создадим новый скрипт, чтобы продемонстрировать манипуляцию массивами:
- В WebIDE создайте новый файл с именем
array_manipulation.sh:
#!/bin/bash
## Create an initial array
fruits=("apple" "banana" "orange")
echo "Initial array: ${fruits[@]}"
## Add an element to the end of the array
fruits+=("grape")
echo "After adding grape: ${fruits[@]}"
## Add multiple elements
fruits+=("kiwi" "mango")
echo "After adding kiwi and mango: ${fruits[@]}"
## Change an element
fruits[1]="blueberry"
echo "After changing banana to blueberry: ${fruits[@]}"
## Remove an element (this leaves an empty slot)
unset fruits[2]
echo "After removing the third element: ${fruits[@]}"
## Print array indices
echo "Array indices: ${!fruits[@]}"
## Recreate array to remove empty slots
new_fruits=()
for fruit in "${fruits[@]}"; do
if [[ -n "$fruit" ]]; then
new_fruits+=("$fruit")
fi
done
fruits=("${new_fruits[@]}")
echo "After removing empty slots: ${fruits[@]}"
- Сохраните файл и сделайте его исполняемым:
chmod +x /home/labex/project/array_manipulation.sh
- Запустите скрипт:
./array_manipulation.sh
Вывод должен показать, как массив изменяется при каждой операции:
Initial array: apple banana orange
After adding grape: apple banana orange grape
After adding kiwi and mango: apple banana orange grape kiwi mango
After changing banana to blueberry: apple blueberry orange grape kiwi mango
After removing the third element: apple blueberry grape kiwi mango
Array indices: 0 1 3 4 5
After removing empty slots: apple blueberry grape kiwi mango
Срезание массивов
Давайте рассмотрим, как извлекать части массива:
- Создайте новый файл с именем
array_slicing.sh:
#!/bin/bash
## Create a sample array
colors=("red" "orange" "yellow" "green" "blue" "indigo" "violet")
echo "Full array: ${colors[@]}"
## Extract a sub-array (starting index and length)
## Syntax: ${array[@]:start:length}
sub_array1=("${colors[@]:1:3}")
echo "Sub-array (indices 1-3): ${sub_array1[@]}"
## Extract from an index to the end
sub_array2=("${colors[@]:4}")
echo "Sub-array (from index 4 to end): ${sub_array2[@]}"
## Extract the last two elements
sub_array3=("${colors[@]: -2}") ## Note the space before -2
echo "Last two elements: ${sub_array3[@]}"
- Сохраните файл и сделайте его исполняемым:
chmod +x /home/labex/project/array_slicing.sh
- Запустите скрипт:
./array_slicing.sh
Вывод продемонстрирует различные способы среза массивов:
Full array: red orange yellow green blue indigo violet
Sub-array (indices 1-3): orange yellow green
Sub-array (from index 4 to end): blue indigo violet
Last two elements: indigo violet
Поиск элементов в массивах
Создадим скрипт, чтобы продемонстрировать, как искать элементы в массиве:
- Создайте новый файл с именем
array_searching.sh:
#!/bin/bash
## Create a sample array
fruits=("apple" "banana" "orange" "grape" "kiwi")
echo "Our fruits: ${fruits[@]}"
## Function to search for an element in an array
search_array() {
local needle="$1"
shift
local haystack=("$@")
for i in "${!haystack[@]}"; do
if [[ "${haystack[$i]}" == "$needle" ]]; then
echo "Found '$needle' at index $i"
return 0
fi
done
echo "'$needle' not found in the array"
return 1
}
## Search for some fruits
search_array "orange" "${fruits[@]}"
search_array "banana" "${fruits[@]}"
search_array "watermelon" "${fruits[@]}"
- Сохраните файл и сделайте его исполняемым:
chmod +x /home/labex/project/array_searching.sh
- Запустите скрипт:
./array_searching.sh
Вывод покажет результаты поиска различных элементов:
Our fruits: apple banana orange grape kiwi
Found 'orange' at index 2
Found 'banana' at index 1
'watermelon' not found in the array
Эти примеры демонстрируют общие операции, которые можно выполнять с массивами Bash, и которые являются важными навыками для работы с наборами данных в ваших скриптах.
Вывод элементов массива по одному в строке
На этом этапе мы сосредоточимся на главной теме нашей лабораторной работы: выводе элементов массива по одному в строке. Мы рассмотрим различные методы для достижения этого в Bash.
Метод 1: Использование цикла for
Самый простой способ вывести элементы массива по одному в строке — использовать цикл for:
- Создайте новый файл с именем
print_array_loop.sh:
#!/bin/bash
## Create a sample array
planets=("Mercury" "Venus" "Earth" "Mars" "Jupiter" "Saturn" "Uranus" "Neptune")
echo "Printing planets using a for loop:"
for planet in "${planets[@]}"; do
echo "$planet"
done
- Сохраните файл и сделайте его исполняемым:
chmod +x /home/labex/project/print_array_loop.sh
- Запустите скрипт:
./print_array_loop.sh
Вывод покажет каждую планету в отдельной строке:
Printing planets using a for loop:
Mercury
Venus
Earth
Mars
Jupiter
Saturn
Uranus
Neptune
Метод 2: Использование команды printf
Команда printf часто более эффективна, чем использование цикла с echo:
- Создайте новый файл с именем
print_array_printf.sh:
#!/bin/bash
## Create a sample array
planets=("Mercury" "Venus" "Earth" "Mars" "Jupiter" "Saturn" "Uranus" "Neptune")
echo "Printing planets using printf:"
printf "%s\n" "${planets[@]}"
- Сохраните файл и сделайте его исполняемым:
chmod +x /home/labex/project/print_array_printf.sh
- Запустите скрипт:
./print_array_printf.sh
Вывод будет таким же, как в предыдущем методе:
Printing planets using printf:
Mercury
Venus
Earth
Mars
Jupiter
Saturn
Uranus
Neptune
Метод 3: Использование переменной IFS
Переменная Internal Field Separator (IFS, разделитель внутренних полей) может быть использована для управления выводом элементов массива:
- Создайте новый файл с именем
print_array_ifs.sh:
#!/bin/bash
## Create a sample array
planets=("Mercury" "Venus" "Earth" "Mars" "Jupiter" "Saturn" "Uranus" "Neptune")
echo "Printing planets using IFS:"
## Temporarily change IFS to newline
old_IFS="$IFS"
IFS=$'\n'
echo "${planets[*]}" ## Note: using * instead of @ with IFS
IFS="$old_IFS" ## Restore original IFS
- Сохраните файл и сделайте его исполняемым:
chmod +x /home/labex/project/print_array_ifs.sh
- Запустите скрипт:
./print_array_ifs.sh
Вывод снова покажет каждую планету в отдельной строке:
Printing planets using IFS:
Mercury
Venus
Earth
Mars
Jupiter
Saturn
Uranus
Neptune
Метод 4: Комбинирование нескольких методов
Давайте объединим эти методы в более комплексном примере:
- Создайте новый файл с именем
print_array_combined.sh:
#!/bin/bash
## Create a sample array
planets=("Mercury" "Venus" "Earth" "Mars" "Jupiter" "Saturn" "Uranus" "Neptune")
echo "Using a for loop with index:"
for i in "${!planets[@]}"; do
echo "Planet $i: ${planets[$i]}"
done
echo -e "\nUsing printf with formatting:"
printf "Planet: %s - %d letters\n" "${planets[@]}" "${#planets[@]}"
echo -e "\nSorted planets:"
printf "%s\n" "${planets[@]}" | sort
- Сохраните файл и сделайте его исполняемым:
chmod +x /home/labex/project/print_array_combined.sh
- Запустите скрипт:
./print_array_combined.sh
Вывод покажет различные способы форматирования и вывода элементов массива:
Using a for loop with index:
Planet 0: Mercury
Planet 1: Venus
Planet 2: Earth
Planet 3: Mars
Planet 4: Jupiter
Planet 5: Saturn
Planet 6: Uranus
Planet 7: Neptune
Using printf with formatting:
Planet: Mercury - 8 letters
Planet: Venus - 5 letters
Planet: Earth - 5 letters
Planet: Mars - 4 letters
Planet: Jupiter - 7 letters
Planet: Saturn - 6 letters
Planet: Uranus - 7 letters
Planet: Neptune - 7 letters
Sorted planets:
Earth
Jupiter
Mars
Mercury
Neptune
Saturn
Uranus
Venus
Каждый из этих методов имеет свои преимущества:
- Цикл for наиболее понятен для начинающих.
- Метод с использованием printf более эффективен для больших массивов.
- Метод с использованием IFS компактный, но может быть менее интуитивно понятным.
- Комбинированные методы могут предоставить богатые возможности форматирования.
Выберите метод, который лучше всего подходит для вашего конкретного случая использования и стиля программирования.
Практические применения массивов
На этом последнем этапе мы рассмотрим реальные применения массивов Bash и применим изученные техники для вывода элементов по одному в строке.
Обработка списка файлов
Создадим скрипт, который обрабатывает файлы в директории:
- Сначала создадим несколько примеров файлов для работы:
mkdir -p /home/labex/project/sample_files
touch /home/labex/project/sample_files/file1.txt
touch /home/labex/project/sample_files/file2.txt
touch /home/labex/project/sample_files/file3.txt
touch /home/labex/project/sample_files/image1.jpg
touch /home/labex/project/sample_files/image2.jpg
- Создайте новый файл с именем
process_files.sh:
#!/bin/bash
## Get a list of files in the directory
file_path="/home/labex/project/sample_files"
files=($(ls "$file_path"))
echo "All files in directory:"
printf "%s\n" "${files[@]}"
echo -e "\nProcessing text files only:"
text_files=()
## Filter for text files
for file in "${files[@]}"; do
if [[ "$file" == *.txt ]]; then
text_files+=("$file")
fi
done
## Process each text file
if [ ${#text_files[@]} -eq 0 ]; then
echo "No text files found."
else
echo "Found ${#text_files[@]} text files:"
for file in "${text_files[@]}"; do
echo "Processing $file..."
## Here you would typically do something with each file
echo " - Adding content to $file"
echo "This is sample content" > "$file_path/$file"
done
fi
## Verify the content
echo -e "\nContent of text files:"
for file in "${text_files[@]}"; do
echo "--- $file ---"
cat "$file_path/$file"
echo "------------"
done
- Сохраните файл и сделайте его исполняемым:
chmod +x /home/labex/project/process_files.sh
- Запустите скрипт:
./process_files.sh
Вывод покажет, как обрабатывать и фильтровать файлы с использованием массивов:
All files in directory:
file1.txt
file2.txt
file3.txt
image1.jpg
image2.jpg
Processing text files only:
Found 3 text files:
Processing file1.txt...
- Adding content to file1.txt
Processing file2.txt...
- Adding content to file2.txt
Processing file3.txt...
- Adding content to file3.txt
Content of text files:
--- file1.txt ---
This is sample content
------------
--- file2.txt ---
This is sample content
------------
--- file3.txt ---
This is sample content
------------
Создание простой системы меню
Массивы могут быть полезны для создания систем меню в скриптах:
- Создайте новый файл с именем
menu_system.sh:
#!/bin/bash
## Define menu options
options=("List Files" "Check Disk Space" "Display Date" "Display Users" "Exit")
while true; do
echo -e "\nMenu Options:"
## Print menu with numbers
for i in "${!options[@]}"; do
echo " $((i + 1)). ${options[$i]}"
done
## Get user choice
read -p "Enter your choice (1-${#options[@]}): " choice
## Convert to zero-based index
((choice--))
## Process choice
case $choice in
0) ## List Files
echo -e "\nFiles in current directory:"
ls -la /home/labex/project
;;
1) ## Check Disk Space
echo -e "\nDisk space usage:"
df -h
;;
2) ## Display Date
echo -e "\nCurrent date and time:"
date
;;
3) ## Display Users
echo -e "\nCurrently logged in users:"
who
;;
4) ## Exit
echo "Exiting menu system. Goodbye!"
exit 0
;;
*)
echo "Invalid choice. Please try again."
;;
esac
## Pause before showing menu again
read -p "Press Enter to continue..."
done
- Сохраните файл и сделайте его исполняемым:
chmod +x /home/labex/project/menu_system.sh
- Запустите скрипт:
./menu_system.sh
- Вы увидите систему меню. Попробуйте выбрать разные опции, чтобы увидеть результаты. Когда закончите, выберите опцию 5 для выхода.
Обработка вывода команд
Массивы отлично подходят для обработки вывода команд:
- Создайте новый файл с именем
process_command_output.sh:
#!/bin/bash
## Get a list of running processes
echo "Getting list of processes..."
processes=($(ps -e | awk '{print $4}' | tail -n +2))
echo "Found ${#processes[@]} processes"
echo -e "\nTop 10 processes:"
printf "%s\n" "${processes[@]:0:10}"
## Count unique processes
echo -e "\nCounting unique process names..."
declare -A process_count
for process in "${processes[@]}"; do
((process_count["$process"]++))
done
echo -e "\nProcess Count Summary:"
for process in "${!process_count[@]}"; do
echo "$process: ${process_count["$process"]}"
done | sort -rn -k2 | head -10
- Сохраните файл и сделайте его исполняемым:
chmod +x /home/labex/project/process_command_output.sh
- Запустите скрипт:
./process_command_output.sh
Вывод покажет, как обрабатывать вывод команд с использованием массивов. Точный вывод будет различаться в зависимости от запущенных процессов на вашей системе.
Эти примеры демонстрируют, как массивы Bash могут быть использованы в реальных сценариях для решения практических задач. Возможность обрабатывать списки элементов и выводить их в удобочитаемом формате является фундаментальным навыком для написания скриптов в оболочке.
Резюме
В этой лабораторной работе вы научились основным навыкам работы с массивами Bash:
Создание и понимание массивов
- Объявление массивов различными методами
- Доступ к элементам и свойствам массива
Манипуляция элементами массива
- Добавление, удаление и изменение элементов
- Создание срезов массивов и поиск элементов
Вывод элементов массива по одному в строке
- Использование циклов for для перебора массивов
- Использование команды printf для эффективного вывода
- Использование переменной IFS для настраиваемого форматирования
- Комбинирование методов для продвинутого форматирования вывода
Практические применения
- Обработка списков файлов
- Создание систем меню
- Обработка вывода команд
Эти навыки предоставляют прочную основу для использования массивов в ваших скриптах Bash. Теперь вы можете эффективно хранить, манипулировать и отображать наборы данных, делая свои скрипты более надежными и гибкими.
Помните, что ключ к овладению массивами Bash - это практика. Попробуйте применить эти методы в своих собственных скриптах и изучите, как они могут помочь эффективно решать реальные проблемы.



