bash скрипты для начинающих — урок №8: Цикл по строкам файла.

Предыдущий урок: bash скрипты для начинающих — урок №7: Цикл for.

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

Когда пригодится построчное чтение файла?

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

Проверка условий, поиск ошибок или фильтрация данных: Например, искать строки, содержащие ошибку, и выполнять для них определённые действия.

Обеспечение гибкости и универсальности сценариев: Построчное чтение — это универсальный способ работать с файлами любой структуры, где важна каждая строка.

Цикл по строкам файла

Подготовим файл скрипта:

[root@waky bash_practice]# touch script_8.sh
[root@waky bash_practice]# chmod +x script_8.sh
[root@waky bash_practice]#

И файл, по которому будет работать цикл:

[root@waky bash_practice]# echo -e "apple\nbanana\ncarambola\ndurian\neggfruit" > fruits.txt
[root@waky bash_practice]#

Теперь у нас есть файл из пяти строк, в каждой строке по одному названию.

Шаг 1: Используем while

Заполним файл script_8.sh следующим кодом:

#!/bin/bash

while read line;
do
 echo "Line in file: $line"
done < ./fruits.txt

Запустим скрипт и проверим результат:

[root@waky bash_practice]# ./script_8.sh
Line in file: apple
Line in file: banana
Line in file: carambola
Line in file: durian
Line in file: eggfruit
[root@waky bash_practice]#

Таким образом, мы можем работать с каждой отдельной строкой.

Шаг 2: Используем for

Мы уже умеем передавать результат исполнения команды как множество элементов для цикла. С содержимым файла можно проделать то же самое. Изменим наш скрипт:

#!/bin/bash

for line in $(cat ./fruits.txt)
do
    echo "Line in file: $line"
done

Проверим результат:

[root@waky bash_practice]# ./script_8.sh
Line in file: apple
Line in file: banana
Line in file: carambola
Line in file: durian
Line in file: eggfruit
[root@waky bash_practice]#

Скрипт отработал, как и ожидалось.

Давайте внесем изменения в наш текстовый файл:

[root@waky bash_practice]# echo -e "apple 3\nbanana 2\ncarambola 7\ndurian 3\neggfruit 5" > fruits.txt
[root@waky bash_practice]#

И модифицируем наш скрипт, собрав в нем оба цикла:

#!/bin/bash

while read line;
do
 echo "while loop line: $line"
done < ./fruits.txt

for line in $(cat ./fruits.txt)
do
    echo "for loop line: $line"
done

Запустим скрипт и проверим результат:

[root@waky bash_practice]# ./script_8.sh
while loop line: apple 3
while loop line: banana 2
while loop line: carambola 7
while loop line: durian 3
while loop line: eggfruit 5
for loop line: apple
for loop line: 3
for loop line: banana
for loop line: 2
for loop line: carambola
for loop line: 7
for loop line: durian
for loop line: 3
for loop line: eggfruit
for loop line: 5
[root@waky bash_practice]#

Как видим, цикл for дал неожиданный результат. При использовании связки cat и for возникает проблема пробелов. Цикл воспринимает каждый пробел, как разделение элементов, поэтому у нас каждое название и каждое число выведено как отдельный элемент.

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

Итоги:

Мы научились читать файлы с помощью циклов и узнали, что while лучше подходит для этой задачи. Чтение файлов широко используется в скриптах, поэтому постарайтесь запомнить эту несложную конструкцию, она вам точно пригодится.

Следующий урок: bash скрипты для начинающих — урок №9: Перенаправление вывода.