Обработка строк на bash циклами while и for

Очень часто в bash скриптах требуется обрабатывать строки, для этого удобно использовать циклы while и for. В статье описан синтаксис обоих циклов для обработки строк, а также особенности их работы.

Цикл while

Синтаксис:

<команда возвращающая строки> | while read line
  do
    <команда обрабатывающая строки> $line
  done

Пример 1. Получаем список пользователей в системе:

#!/bin/bash
cat /etc/passwd | cut -f 1 -d ":" | while read line
  do
    echo "В системе есть пользователь - $line"
  done

Пример 2. Выводим список процессов текущего пользователя:

#!/bin/bash
ps -u $USER -o pid | grep -v PID | while read line
  do
    ps -p $line -o pid,comm,rss -h
  done

Особенности:

  • Чтение происходит построчно, даже если строка содержит пробелы или специальные символы.
  • Корректно обрабатывает строки с пробелами и табуляциями.
  • Работает в подоболочке, поэтому переменные, измененные внутри цикла, не сохранятся в родительской оболочке.
  • Подходит для обработки вывода команд, которые могут возвращать много данных (потоковая обработка).
  • Для обработки строк предпочтительнее использовать этот вариант.

Цикл for

Синтаксис:

for line in `<команда возвращающая строки>`
  do
    <команда обрабатывающая строки> $line
  done

Пример 1. Получаем список пользователей в системе:

#!/bin/bash
for line in `cat /etc/passwd | cut -f 1 -d ":"`
  do
    echo "В системе есть пользователь - $line"
  done

Пример 2. Выводим список процессов текущего пользователя:

#!/bin/bash
for line in `ps -u $USER -o pid | grep -v PID`
  do
    ps -p $line -o pid,comm,rss -h
  done

Особенности:

  • Если строки содержат пробелы, они будут разбиты на отдельные «слова». Не подходит для обработки строк с пробелами.
  • Выполняется в текущей оболочке (переменные сохраняются).
  • Загружает весь вывод команды в память перед обработкой (может быть проблемой для больших данных).
  • Используйте этот вариант только если нужно сохранить переменные после завершения цикла.

Кстати, когда данные уже находятся в массиве, for работает быстрее и проще:

files=(file1.txt file2.txt "file with space.txt")
for file in "${files[@]}"; do
    echo "Обработка: $file"
done

Если понравилась статья, подпишись на мой канал в VK или Telegram.

Возможно вам понравятся и другие статьи:

Мы используем cookie-файлы для наилучшего представления нашего сайта. Продолжая использовать этот сайт, вы соглашаетесь с использованием cookie-файлов.
Принять
Отказаться
Политика конфиденциальности