Как вывести элементы массива Bash по одному в строке

ShellShellBeginner
Практиковаться сейчас

💡 Этот учебник переведен с английского с помощью ИИ. Чтобы просмотреть оригинал, вы можете перейти на английский оригинал

Введение

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

К концу этого практического занятия (LabEx) вы поймете, как создавать массивы, манипулировать элементами массива и использовать различные методы для вывода содержимого массива по одному элементу на строку. Эти навыки помогут вам писать более эффективные и читаемые оболочечные скрипты для таких задач, как обработка списков файлов, обработка выходных данных команд и автоматизация задач системного администрирования.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL shell(("Shell")) -.-> shell/VariableHandlingGroup(["Variable Handling"]) shell(("Shell")) -.-> shell/ControlFlowGroup(["Control Flow"]) shell/VariableHandlingGroup -.-> shell/variables_usage("Variable Usage") shell/VariableHandlingGroup -.-> shell/arrays("Arrays") shell/ControlFlowGroup -.-> shell/case("Case Statements") shell/ControlFlowGroup -.-> shell/for_loops("For Loops") subgraph Lab Skills shell/variables_usage -.-> lab-392979{{"Как вывести элементы массива Bash по одному в строке"}} shell/arrays -.-> lab-392979{{"Как вывести элементы массива Bash по одному в строке"}} shell/case -.-> lab-392979{{"Как вывести элементы массива Bash по одному в строке"}} shell/for_loops -.-> lab-392979{{"Как вывести элементы массива Bash по одному в строке"}} end

Создание и понимание массивов Bash

Массивы Bash позволяют хранить несколько значений в одной переменной. Давайте научимся создавать их и работать с ними.

Создание первого массива

Откройте терминал в WebIDE. По умолчанию вы должны находиться в директории /home/labex/project. Начнем с создания простого скрипта Bash:

  1. В WebIDE создайте новый файл с именем array_demo.sh, нажав на иконку "New File" в панели проводника или выбрав опцию меню "File > New File".

  2. Добавьте в файл следующее содержимое:

#!/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[@]}"
  1. Сохраните файл, нажав Ctrl+S или выбрав опцию меню "File > Save".

  2. Теперь сделайте скрипт исполняемым, запустив следующую команду в терминале:

chmod +x /home/labex/project/array_demo.sh
  1. Запустите скрипт:
./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[@]}
    Символ # перед ссылкой на массив возвращает количество элементов.

Различные способы создания массивов

Создадим новый скрипт, чтобы продемонстрировать различные способы создания массивов:

  1. Создайте новый файл с именем 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[@]}"
  1. Сохраните файл и сделайте его исполняемым:
chmod +x /home/labex/project/array_creation.sh
  1. Запустите скрипт:
./array_creation.sh

Вы должны увидеть вывод, показывающий все различные массивы, которые вы создали. Точный вывод для массива файлов будет зависеть от того, какие файлы существуют в вашей директории.

Эти примеры демонстрируют гибкость массивов Bash и то, как вы можете создавать их различными способами в зависимости от своих потребностей.

Манипуляция элементами массива

Теперь, когда мы знаем, как создавать массивы, давайте научимся манипулировать ими, добавляя, удаляя и изменяя элементы.

Изменение элементов массива

Создадим новый скрипт, чтобы продемонстрировать манипуляцию массивами:

  1. В 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[@]}"
  1. Сохраните файл и сделайте его исполняемым:
chmod +x /home/labex/project/array_manipulation.sh
  1. Запустите скрипт:
./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

Срезание массивов

Давайте рассмотрим, как извлекать части массива:

  1. Создайте новый файл с именем 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[@]}"
  1. Сохраните файл и сделайте его исполняемым:
chmod +x /home/labex/project/array_slicing.sh
  1. Запустите скрипт:
./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

Поиск элементов в массивах

Создадим скрипт, чтобы продемонстрировать, как искать элементы в массиве:

  1. Создайте новый файл с именем 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[@]}"
  1. Сохраните файл и сделайте его исполняемым:
chmod +x /home/labex/project/array_searching.sh
  1. Запустите скрипт:
./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:

  1. Создайте новый файл с именем 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
  1. Сохраните файл и сделайте его исполняемым:
chmod +x /home/labex/project/print_array_loop.sh
  1. Запустите скрипт:
./print_array_loop.sh

Вывод покажет каждую планету в отдельной строке:

Printing planets using a for loop:
Mercury
Venus
Earth
Mars
Jupiter
Saturn
Uranus
Neptune

Метод 2: Использование команды printf

Команда printf часто более эффективна, чем использование цикла с echo:

  1. Создайте новый файл с именем 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[@]}"
  1. Сохраните файл и сделайте его исполняемым:
chmod +x /home/labex/project/print_array_printf.sh
  1. Запустите скрипт:
./print_array_printf.sh

Вывод будет таким же, как в предыдущем методе:

Printing planets using printf:
Mercury
Venus
Earth
Mars
Jupiter
Saturn
Uranus
Neptune

Метод 3: Использование переменной IFS

Переменная Internal Field Separator (IFS, разделитель внутренних полей) может быть использована для управления выводом элементов массива:

  1. Создайте новый файл с именем 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
  1. Сохраните файл и сделайте его исполняемым:
chmod +x /home/labex/project/print_array_ifs.sh
  1. Запустите скрипт:
./print_array_ifs.sh

Вывод снова покажет каждую планету в отдельной строке:

Printing planets using IFS:
Mercury
Venus
Earth
Mars
Jupiter
Saturn
Uranus
Neptune

Метод 4: Комбинирование нескольких методов

Давайте объединим эти методы в более комплексном примере:

  1. Создайте новый файл с именем 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
  1. Сохраните файл и сделайте его исполняемым:
chmod +x /home/labex/project/print_array_combined.sh
  1. Запустите скрипт:
./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 и применим изученные техники для вывода элементов по одному в строке.

Обработка списка файлов

Создадим скрипт, который обрабатывает файлы в директории:

  1. Сначала создадим несколько примеров файлов для работы:
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
  1. Создайте новый файл с именем 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
  1. Сохраните файл и сделайте его исполняемым:
chmod +x /home/labex/project/process_files.sh
  1. Запустите скрипт:
./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
------------

Создание простой системы меню

Массивы могут быть полезны для создания систем меню в скриптах:

  1. Создайте новый файл с именем 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
  1. Сохраните файл и сделайте его исполняемым:
chmod +x /home/labex/project/menu_system.sh
  1. Запустите скрипт:
./menu_system.sh
  1. Вы увидите систему меню. Попробуйте выбрать разные опции, чтобы увидеть результаты. Когда закончите, выберите опцию 5 для выхода.

Обработка вывода команд

Массивы отлично подходят для обработки вывода команд:

  1. Создайте новый файл с именем 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
  1. Сохраните файл и сделайте его исполняемым:
chmod +x /home/labex/project/process_command_output.sh
  1. Запустите скрипт:
./process_command_output.sh

Вывод покажет, как обрабатывать вывод команд с использованием массивов. Точный вывод будет различаться в зависимости от запущенных процессов на вашей системе.

Эти примеры демонстрируют, как массивы Bash могут быть использованы в реальных сценариях для решения практических задач. Возможность обрабатывать списки элементов и выводить их в удобочитаемом формате является фундаментальным навыком для написания скриптов в оболочке.

Резюме

В этой лабораторной работе вы научились основным навыкам работы с массивами Bash:

  1. Создание и понимание массивов

    • Объявление массивов различными методами
    • Доступ к элементам и свойствам массива
  2. Манипуляция элементами массива

    • Добавление, удаление и изменение элементов
    • Создание срезов массивов и поиск элементов
  3. Вывод элементов массива по одному в строке

    • Использование циклов for для перебора массивов
    • Использование команды printf для эффективного вывода
    • Использование переменной IFS для настраиваемого форматирования
    • Комбинирование методов для продвинутого форматирования вывода
  4. Практические применения

    • Обработка списков файлов
    • Создание систем меню
    • Обработка вывода команд

Эти навыки предоставляют прочную основу для использования массивов в ваших скриптах Bash. Теперь вы можете эффективно хранить, манипулировать и отображать наборы данных, делая свои скрипты более надежными и гибкими.

Помните, что ключ к овладению массивами Bash - это практика. Попробуйте применить эти методы в своих собственных скриптах и изучите, как они могут помочь эффективно решать реальные проблемы.