Предыдущий урок: 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: Перенаправление вывода.